[/ (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_logical_not has_logical_not] template struct has_logical_not : 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_logical_not::value==true `` If `Ret=void`, the return type is checked to be exactly `void`. __header `#include ` or `#include ` or `#include ` [has_binary_operator_compat] __examples [:`has_logical_not::value_type` is the type `bool`.] [:`has_logical_not::value` is a `bool` integral constant expression.] [:`has_logical_not::value` is a `bool` integral constant expression that evaluates to `true`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` inherits from `__true_type`.] [:`has_logical_not` 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_logical_not` will produce a compiler error. For this reason `has_logical_not` cannot be used to determine whether a type has a public `operator!` or not. `` struct A { private: void operator!(); }; boost::has_logical_not::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_logical_not::value; // this is fine boost::has_logical_not::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 #include template struct contains { T data; }; template bool operator!(const contains &rhs) { return f(rhs.data); } class bad { }; class good { }; bool f(const good&) { } int main() { std::cout< std::cout< >::value<<'\n'; // true contains g; !g; // ok // does not work for contains std::cout< >::value<<'\n'; // true, should be false contains b; !b; // compile time error return 0; } `` * `volatile` qualifier is not properly handled and would lead to undefined behavior [endsect]