| [/ |
| (C) Copyright 2009-2011 Frederic Bron. |
| Distributed under the Boost Software License, Version 1.0. |
| (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt). |
| ] |
| |
| [section:has_complement has_complement] |
| template <class Rhs, class Ret=dont_care> |
| struct has_complement : public __tof {}; |
| |
| __inherit |
| If (i) `rhs` of type `Rhs` can be used in expression `~rhs`, |
| and (ii) `Ret=dont_care` or the result of expression `~rhs` is convertible to `Ret` |
| then inherits from __true_type, |
| otherwise inherits from __false_type. |
| |
| The default behaviour (`Ret=dont_care`) is to not check for the return value of prefix `operator~`. |
| If `Ret` is different from the default `dont_care` type, the return value is checked to be convertible to `Ret`. |
| Convertible to `Ret` means that the return value of the operator can be used as argument to a function expecting `Ret`: |
| `` |
| void f(Ret); |
| Rhs rhs; |
| f(~rhs); // is valid if has_complement<Rhs, Ret>::value==true |
| `` |
| If `Ret=void`, the return type is checked to be exactly `void`. |
| |
| __header `#include <boost/type_traits/has_complement.hpp>` or `#include <boost/type_traits/has_operator.hpp>` or `#include <boost/type_traits.hpp>` |
| |
| [has_binary_operator_compat] |
| |
| __examples |
| |
| [:`has_complement<Rhs, Ret>::value_type` is the type `bool`.] |
| [:`has_complement<Rhs, Ret>::value` is a `bool` integral constant expression.] |
| [:`has_complement<int>::value` is a `bool` integral constant expression that evaluates to `true`.] |
| [:`has_complement<long>` inherits from `__true_type`.] |
| |
| [:`has_complement<int, int>` inherits from `__true_type`.] |
| [:`has_complement<int, long>` inherits from `__true_type`.] |
| [:`has_complement<const int>` inherits from `__true_type`.] |
| |
| [:`has_complement<int*>` inherits from `__false_type`.] |
| [:`has_complement<double, double>` inherits from `__false_type`.] |
| [:`has_complement<double, int>` inherits from `__false_type`.] |
| [:`has_complement<int, std::string>` inherits from `__false_type`.] |
| |
| |
| [*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits] |
| |
| [*Known issues:] |
| |
| * This trait cannot detect whether prefix `operator~` is public or not: |
| if `operator~` is defined as a private member of `Rhs` then |
| instantiating `has_complement<Rhs>` will produce a compiler error. |
| For this reason `has_complement` cannot be used to determine whether a type has a public `operator~` or not. |
| `` |
| struct A { private: void operator~(); }; |
| boost::has_complement<A>::value; // error: A::operator~() is private |
| `` |
| |
| * There is an issue if the operator exists only for type `A` and `B` is |
| convertible to `A`. In this case, the compiler will report an ambiguous overload. |
| `` |
| struct A { }; |
| void operator~(const A&); |
| struct B { operator A(); }; |
| boost::has_complement<A>::value; // this is fine |
| boost::has_complement<B>::value; // error: ambiguous overload |
| `` |
| |
| * There is an issue when applying this trait to template classes. |
| If `operator~` is defined but does not bind for a given template type, |
| it is still detected by the trait which returns `true` instead of `false`. |
| Example: |
| `` |
| #include <boost/type_traits/has_complement.hpp> |
| #include <iostream> |
| |
| template <class T> |
| struct contains { T data; }; |
| |
| template <class T> |
| bool operator~(const contains<T> &rhs) { |
| return f(rhs.data); |
| } |
| |
| class bad { }; |
| class good { }; |
| bool f(const good&) { } |
| |
| int main() { |
| std::cout<<std::boolalpha; |
| // works fine for contains<good> |
| std::cout<<boost::has_complement< contains< good > >::value<<'\n'; // true |
| contains<good> g; |
| ~g; // ok |
| // does not work for contains<bad> |
| std::cout<<boost::has_complement< contains< bad > >::value<<'\n'; // true, should be false |
| contains<bad> b; |
| ~b; // compile time error |
| return 0; |
| } |
| `` |
| |
| * `volatile` qualifier is not properly handled and would lead to undefined behavior |
| |
| [endsect] |
| |