Update docs for binary operator traits.

This commit is contained in:
jzmaddock
2018-02-11 11:31:23 +00:00
parent 014ac72782
commit 0155b7030c
61 changed files with 1884 additions and 2958 deletions

View File

@ -46,62 +46,7 @@ __examples
[has_binary_operator_compat]
[*Known issues:]
* This trait cannot detect whether binary `operator&` is public or not:
if `operator&` is defined as a private member of `Lhs` then
instantiating `has_bit_and<Lhs>` will produce a compiler error.
For this reason `has_bit_and` cannot be used to determine whether a type has a public `operator&` or not.
``
struct A { private: void operator&(const A&); };
boost::has_bit_and<A>::value; // error: A::operator&(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_and<A>::value; // this is fine
boost::has_bit_and<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_bit_and.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator&(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_and< contains< good > >::value<<'\n'; // true
contains<good> g;
g&g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_and< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b&b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_and..&..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator&=` is public or not:
if `operator&=` is defined as a private member of `Lhs` then
instantiating `has_bit_and_assign<Lhs>` will produce a compiler error.
For this reason `has_bit_and_assign` cannot be used to determine whether a type has a public `operator&=` or not.
``
struct A { private: void operator&=(const A&); };
boost::has_bit_and_assign<A>::value; // error: A::operator&=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_and_assign<A>::value; // this is fine
boost::has_bit_and_assign<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_bit_and_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator&=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_and_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g&=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_and_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b&=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_and_assign..&=..A&..contains<T>&..[/Nothing]]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator|` is public or not:
if `operator|` is defined as a private member of `Lhs` then
instantiating `has_bit_or<Lhs>` will produce a compiler error.
For this reason `has_bit_or` cannot be used to determine whether a type has a public `operator|` or not.
``
struct A { private: void operator|(const A&); };
boost::has_bit_or<A>::value; // error: A::operator|(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_or<A>::value; // this is fine
boost::has_bit_or<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_bit_or.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator|(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_or< contains< good > >::value<<'\n'; // true
contains<good> g;
g|g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_or< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b|b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_or..|..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator|=` is public or not:
if `operator|=` is defined as a private member of `Lhs` then
instantiating `has_bit_or_assign<Lhs>` will produce a compiler error.
For this reason `has_bit_or_assign` cannot be used to determine whether a type has a public `operator|=` or not.
``
struct A { private: void operator|=(const A&); };
boost::has_bit_or_assign<A>::value; // error: A::operator|=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_or_assign<A>::value; // this is fine
boost::has_bit_or_assign<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_bit_or_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator|=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_or_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g|=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_or_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b|=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_or_assign..|=..A&..contains<T>&..[/Nothing]]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator^` is public or not:
if `operator^` is defined as a private member of `Lhs` then
instantiating `has_bit_xor<Lhs>` will produce a compiler error.
For this reason `has_bit_xor` cannot be used to determine whether a type has a public `operator^` or not.
``
struct A { private: void operator^(const A&); };
boost::has_bit_xor<A>::value; // error: A::operator^(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_xor<A>::value; // this is fine
boost::has_bit_xor<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_bit_xor.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator^(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_xor< contains< good > >::value<<'\n'; // true
contains<good> g;
g^g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_xor< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b^b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_xor..^..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator^=` is public or not:
if `operator^=` is defined as a private member of `Lhs` then
instantiating `has_bit_xor_assign<Lhs>` will produce a compiler error.
For this reason `has_bit_xor_assign` cannot be used to determine whether a type has a public `operator^=` or not.
``
struct A { private: void operator^=(const A&); };
boost::has_bit_xor_assign<A>::value; // error: A::operator^=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_bit_xor_assign<A>::value; // this is fine
boost::has_bit_xor_assign<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_bit_xor_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator^=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_bit_xor_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g^=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_bit_xor_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b^=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_bit_xor_assign..^=..A&..contains<T>&..[/Nothing]]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator/` is public or not:
if `operator/` is defined as a private member of `Lhs` then
instantiating `has_divides<Lhs>` will produce a compiler error.
For this reason `has_divides` cannot be used to determine whether a type has a public `operator/` or not.
``
struct A { private: void operator/(const A&); };
boost::has_divides<A>::value; // error: A::operator/(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_divides<A>::value; // this is fine
boost::has_divides<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_divides.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator/(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_divides< contains< good > >::value<<'\n'; // true
contains<good> g;
g/g; // ok
// does not work for contains<bad>
std::cout<<boost::has_divides< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b/b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_divides../..A..contains<T>..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator/=` is public or not:
if `operator/=` is defined as a private member of `Lhs` then
instantiating `has_divides_assign<Lhs>` will produce a compiler error.
For this reason `has_divides_assign` cannot be used to determine whether a type has a public `operator/=` or not.
``
struct A { private: void operator/=(const A&); };
boost::has_divides_assign<A>::value; // error: A::operator/=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_divides_assign<A>::value; // this is fine
boost::has_divides_assign<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_divides_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator/=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_divides_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g/=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_divides_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b/=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_divides_assign../=..A&..contains<T>&..[/Nothing]]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator==` is public or not:
if `operator==` is defined as a private member of `Lhs` then
instantiating `has_equal_to<Lhs>` will produce a compiler error.
For this reason `has_equal_to` cannot be used to determine whether a type has a public `operator==` or not.
``
struct A { private: void operator==(const A&); };
boost::has_equal_to<A>::value; // error: A::operator==(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_equal_to<A>::value; // this is fine
boost::has_equal_to<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_equal_to.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator==(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_equal_to< contains< good > >::value<<'\n'; // true
contains<good> g;
g==g; // ok
// does not work for contains<bad>
std::cout<<boost::has_equal_to< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b==b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_equal_to..==..bool..bool..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator>` is public or not:
if `operator>` is defined as a private member of `Lhs` then
instantiating `has_greater<Lhs>` will produce a compiler error.
For this reason `has_greater` cannot be used to determine whether a type has a public `operator>` or not.
``
struct A { private: void operator>(const A&); };
boost::has_greater<A>::value; // error: A::operator>(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_greater<A>::value; // this is fine
boost::has_greater<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_greater.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator>(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_greater< contains< good > >::value<<'\n'; // true
contains<good> g;
g>g; // ok
// does not work for contains<bad>
std::cout<<boost::has_greater< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b>b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_greater..>..bool..bool..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator>=` is public or not:
if `operator>=` is defined as a private member of `Lhs` then
instantiating `has_greater_equal<Lhs>` will produce a compiler error.
For this reason `has_greater_equal` cannot be used to determine whether a type has a public `operator>=` or not.
``
struct A { private: void operator>=(const A&); };
boost::has_greater_equal<A>::value; // error: A::operator>=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_greater_equal<A>::value; // this is fine
boost::has_greater_equal<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_greater_equal.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator>=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_greater_equal< contains< good > >::value<<'\n'; // true
contains<good> g;
g>=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_greater_equal< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b>=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_greater_equal..>=..bool..bool..const ]
[endsect]

View File

@ -49,62 +49,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator<<` is public or not:
if `operator<<` is defined as a private member of `Lhs` then
instantiating `has_left_shift<Lhs>` will produce a compiler error.
For this reason `has_left_shift` cannot be used to determine whether a type has a public `operator<<` or not.
``
struct A { private: void operator<<(const A&); };
boost::has_left_shift<A>::value; // error: A::operator<<(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_left_shift<A>::value; // this is fine
boost::has_left_shift<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_left_shift.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator<<(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_left_shift< contains< good > >::value<<'\n'; // true
contains<good> g;
g<<g; // ok
// does not work for contains<bad>
std::cout<<boost::has_left_shift< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b<<b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_left_shift..<<..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator<<=` is public or not:
if `operator<<=` is defined as a private member of `Lhs` then
instantiating `has_left_shift_assign<Lhs>` will produce a compiler error.
For this reason `has_left_shift_assign` cannot be used to determine whether a type has a public `operator<<=` or not.
``
struct A { private: void operator<<=(const A&); };
boost::has_left_shift_assign<A>::value; // error: A::operator<<=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_left_shift_assign<A>::value; // this is fine
boost::has_left_shift_assign<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_left_shift_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator<<=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_left_shift_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g<<=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_left_shift_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b<<=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_left_shift_assign..<<=..A&..contains<T>&..[/]]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator<` is public or not:
if `operator<` is defined as a private member of `Lhs` then
instantiating `has_less<Lhs>` will produce a compiler error.
For this reason `has_less` cannot be used to determine whether a type has a public `operator<` or not.
``
struct A { private: void operator<(const A&); };
boost::has_less<A>::value; // error: A::operator<(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_less<A>::value; // this is fine
boost::has_less<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_less.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator<(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_less< contains< good > >::value<<'\n'; // true
contains<good> g;
g<g; // ok
// does not work for contains<bad>
std::cout<<boost::has_less< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b<b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_less..<..bool..bool..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator<=` is public or not:
if `operator<=` is defined as a private member of `Lhs` then
instantiating `has_less_equal<Lhs>` will produce a compiler error.
For this reason `has_less_equal` cannot be used to determine whether a type has a public `operator<=` or not.
``
struct A { private: void operator<=(const A&); };
boost::has_less_equal<A>::value; // error: A::operator<=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_less_equal<A>::value; // this is fine
boost::has_less_equal<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_less_equal.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator<=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_less_equal< contains< good > >::value<<'\n'; // true
contains<good> g;
g<=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_less_equal< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b<=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_less_equal..<=..bool..bool..const ]
[endsect]

View File

@ -46,63 +46,8 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[binary_operator_known_issues has_logical_and..&&..bool..bool..const ]
[*Known issues:]
* This trait cannot detect whether binary `operator&&` is public or not:
if `operator&&` is defined as a private member of `Lhs` then
instantiating `has_logical_and<Lhs>` will produce a compiler error.
For this reason `has_logical_and` cannot be used to determine whether a type has a public `operator&&` or not.
``
struct A { private: void operator&&(const A&); };
boost::has_logical_and<A>::value; // error: A::operator&&(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_logical_and<A>::value; // this is fine
boost::has_logical_and<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_logical_and.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator&&(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_logical_and< contains< good > >::value<<'\n'; // true
contains<good> g;
g&&g; // ok
// does not work for contains<bad>
std::cout<<boost::has_logical_and< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b&&b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[endsect]

View File

@ -47,62 +47,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator||` is public or not:
if `operator||` is defined as a private member of `Lhs` then
instantiating `has_logical_or<Lhs>` will produce a compiler error.
For this reason `has_logical_or` cannot be used to determine whether a type has a public `operator||` or not.
``
struct A { private: void operator||(const A&); };
boost::has_logical_or<A>::value; // error: A::operator||(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_logical_or<A>::value; // this is fine
boost::has_logical_or<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_logical_or.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator||(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_logical_or< contains< good > >::value<<'\n'; // true
contains<good> g;
g||g; // ok
// does not work for contains<bad>
std::cout<<boost::has_logical_or< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b||b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_logical_or..||..bool..bool..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator-` is public or not:
if `operator-` is defined as a private member of `Lhs` then
instantiating `has_minus<Lhs>` will produce a compiler error.
For this reason `has_minus` cannot be used to determine whether a type has a public `operator-` or not.
``
struct A { private: void operator-(const A&); };
boost::has_minus<A>::value; // error: A::operator-(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_minus<A>::value; // this is fine
boost::has_minus<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_minus.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator-(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_minus< contains< good > >::value<<'\n'; // true
contains<good> g;
g-g; // ok
// does not work for contains<bad>
std::cout<<boost::has_minus< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b-b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_minus..-..A..contains<T>..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator-=` is public or not:
if `operator-=` is defined as a private member of `Lhs` then
instantiating `has_minus_assign<Lhs>` will produce a compiler error.
For this reason `has_minus_assign` cannot be used to determine whether a type has a public `operator-=` or not.
``
struct A { private: void operator-=(const A&); };
boost::has_minus_assign<A>::value; // error: A::operator-=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_minus_assign<A>::value; // this is fine
boost::has_minus_assign<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_minus_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator-=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_minus_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g-=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_minus_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b-=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_minus_assign..-=..A&..contains<T>&..[/]]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator%` is public or not:
if `operator%` is defined as a private member of `Lhs` then
instantiating `has_modulus<Lhs>` will produce a compiler error.
For this reason `has_modulus` cannot be used to determine whether a type has a public `operator%` or not.
``
struct A { private: void operator%(const A&); };
boost::has_modulus<A>::value; // error: A::operator%(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_modulus<A>::value; // this is fine
boost::has_modulus<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_modulus.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator%(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_modulus< contains< good > >::value<<'\n'; // true
contains<good> g;
g%g; // ok
// does not work for contains<bad>
std::cout<<boost::has_modulus< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b%b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_modulus..%..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator%=` is public or not:
if `operator%=` is defined as a private member of `Lhs` then
instantiating `has_modulus_assign<Lhs>` will produce a compiler error.
For this reason `has_modulus_assign` cannot be used to determine whether a type has a public `operator%=` or not.
``
struct A { private: void operator%=(const A&); };
boost::has_modulus_assign<A>::value; // error: A::operator%=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_modulus_assign<A>::value; // this is fine
boost::has_modulus_assign<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_modulus_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator%=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_modulus_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g%=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_modulus_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b%=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_modulus_assign..%=..A&..contains<T>&..[/]]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator*` is public or not:
if `operator*` is defined as a private member of `Lhs` then
instantiating `has_multiplies<Lhs>` will produce a compiler error.
For this reason `has_multiplies` cannot be used to determine whether a type has a public `operator*` or not.
``
struct A { private: void operator*(const A&); };
boost::has_multiplies<A>::value; // error: A::operator*(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_multiplies<A>::value; // this is fine
boost::has_multiplies<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_multiplies.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator*(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_multiplies< contains< good > >::value<<'\n'; // true
contains<good> g;
g*g; // ok
// does not work for contains<bad>
std::cout<<boost::has_multiplies< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b*b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_multiplies..*..A..contains<T>..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator*=` is public or not:
if `operator*=` is defined as a private member of `Lhs` then
instantiating `has_multiplies_assign<Lhs>` will produce a compiler error.
For this reason `has_multiplies_assign` cannot be used to determine whether a type has a public `operator*=` or not.
``
struct A { private: void operator*=(const A&); };
boost::has_multiplies_assign<A>::value; // error: A::operator*=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_multiplies_assign<A>::value; // this is fine
boost::has_multiplies_assign<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_multiplies_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator*=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_multiplies_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g*=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_multiplies_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b*=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_multiplies_assign..*=..A&..contains<T>&..[/]]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator!=` is public or not:
if `operator!=` is defined as a private member of `Lhs` then
instantiating `has_not_equal_to<Lhs>` will produce a compiler error.
For this reason `has_not_equal_to` cannot be used to determine whether a type has a public `operator!=` or not.
``
struct A { private: void operator!=(const A&); };
boost::has_not_equal_to<A>::value; // error: A::operator!=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_not_equal_to<A>::value; // this is fine
boost::has_not_equal_to<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_not_equal_to.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator!=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_not_equal_to< contains< good > >::value<<'\n'; // true
contains<good> g;
g!=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_not_equal_to< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b!=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_not_equal_to..!=..bool..bool..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator+` is public or not:
if `operator+` is defined as a private member of `Lhs` then
instantiating `has_plus<Lhs>` will produce a compiler error.
For this reason `has_plus` cannot be used to determine whether a type has a public `operator+` or not.
``
struct A { private: void operator+(const A&); };
boost::has_plus<A>::value; // error: A::operator+(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_plus<A>::value; // this is fine
boost::has_plus<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_plus.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator+(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_plus< contains< good > >::value<<'\n'; // true
contains<good> g;
g+g; // ok
// does not work for contains<bad>
std::cout<<boost::has_plus< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b+b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_plus..+..A..contains<T>..const ]
[endsect]

View File

@ -48,62 +48,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator+=` is public or not:
if `operator+=` is defined as a private member of `Lhs` then
instantiating `has_plus_assign<Lhs>` will produce a compiler error.
For this reason `has_plus_assign` cannot be used to determine whether a type has a public `operator+=` or not.
``
struct A { private: void operator+=(const A&); };
boost::has_plus_assign<A>::value; // error: A::operator+=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_plus_assign<A>::value; // this is fine
boost::has_plus_assign<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_plus_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator+=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_plus_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g+=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_plus_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b+=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_plus_assign..+=..A&..contains<T>&..const ]
[endsect]

View File

@ -49,62 +49,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator>>` is public or not:
if `operator>>` is defined as a private member of `Lhs` then
instantiating `has_right_shift<Lhs>` will produce a compiler error.
For this reason `has_right_shift` cannot be used to determine whether a type has a public `operator>>` or not.
``
struct A { private: void operator>>(const A&); };
boost::has_right_shift<A>::value; // error: A::operator>>(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_right_shift<A>::value; // this is fine
boost::has_right_shift<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_right_shift.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator>>(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_right_shift< contains< good > >::value<<'\n'; // true
contains<good> g;
g>>g; // ok
// does not work for contains<bad>
std::cout<<boost::has_right_shift< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b>>b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_right_shift..>>..A..contains<T>..const ]
[endsect]

View File

@ -46,62 +46,7 @@ __examples
[*See also:] [link boost_typetraits.category.value_traits.operators Operator Type Traits]
[*Known issues:]
* This trait cannot detect whether binary `operator>>=` is public or not:
if `operator>>=` is defined as a private member of `Lhs` then
instantiating `has_right_shift_assign<Lhs>` will produce a compiler error.
For this reason `has_right_shift_assign` cannot be used to determine whether a type has a public `operator>>=` or not.
``
struct A { private: void operator>>=(const A&); };
boost::has_right_shift_assign<A>::value; // error: A::operator>>=(const A&) 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&, const A&);
struct B { operator A(); };
boost::has_right_shift_assign<A>::value; // this is fine
boost::has_right_shift_assign<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_right_shift_assign.hpp>
#include <iostream>
template <class T>
struct contains { T data; };
template <class T>
bool operator>>=(const contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
bool f(const good&, const good&) { }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::has_right_shift_assign< contains< good > >::value<<'\n'; // true
contains<good> g;
g>>=g; // ok
// does not work for contains<bad>
std::cout<<boost::has_right_shift_assign< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b>>=b; // compile time error
return 0;
}
``
* `volatile` qualifier is not properly handled and would lead to undefined behavior
[binary_operator_known_issues has_right_shift_assign..>>=..A&..contains<T>&..[/]]
[endsect]

View File

@ -107,68 +107,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_bit_and</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_bit_and</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&amp;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_and</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_and.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_and cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_and<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&amp;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> &amp; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_and<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_and<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&amp;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&amp;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_and&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_bit_and</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&amp;
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> &amp; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &amp; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> &amp; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,68 +107,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_bit_and_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&amp;=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_and_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_and_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_and_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_and_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&amp;=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> &amp;= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_and_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_and_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_and_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&amp;=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&amp;=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_and_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_bit_and_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&amp;= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> &amp;= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &amp;= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> &amp;= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_and_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,66 +107,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">|</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">|</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_bit_or</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_bit_or</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">|</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">|(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator|(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">|(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">|</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_or</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_or.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_or cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_or<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">|(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> | <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">|</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">|</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_or<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_or<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>|
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>|
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_or&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_bit_or</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>|
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> | <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator | (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> | <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,68 +107,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">|=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">|=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_bit_or_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">|=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">|=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator|=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">|=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">|=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_or_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_or_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_or_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_or_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">|=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> |= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">|=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_or_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">|=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_or_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_or_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>|=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>|=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_or_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_bit_or_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>|= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> |= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator |= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> |= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_or_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,66 +107,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">^</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">^</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_bit_xor</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_bit_xor</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">^</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">^(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator^(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">^(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">^</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_xor</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_xor.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_xor cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_xor<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">^(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> ^ <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">^</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">^</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_xor<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_xor<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>^
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>^
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_xor&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_bit_xor</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>^
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> ^ <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator ^ (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> ^ <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,68 +107,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">^=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">^=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_bit_xor_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">^=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">^=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator^=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">^=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">^=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_bit_xor_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_bit_xor_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_bit_xor_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_bit_xor_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">^=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> ^= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">^=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_bit_xor_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">^=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_xor_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_bit_xor_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>^=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>^=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_bit_xor_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_bit_xor_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>^= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> ^= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator ^= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> ^= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_bit_xor_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,66 +113,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">/</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">/</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_divides</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_divides</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">/</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">/(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator/(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">/(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">/</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_divides</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_divides.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_divides cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_divides<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">/(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> / <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">/</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">/</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_divides<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_divides<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>/
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>/
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_divides&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_divides</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>/
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> / <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator / (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> / <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,68 +113,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">/=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">/=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_divides_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_divides_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">/=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">/=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator/=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">/=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">/=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_divides_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_divides_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_divides_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_divides_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">/=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> /= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">/=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_divides_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">/=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_divides_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_divides_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>/=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>/=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_divides_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_divides_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>/= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> /= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator /= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> /= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_divides_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">==</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">==</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_equal_to</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_equal_to</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">==</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">==(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator==(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">==(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">==</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_equal_to</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_equal_to.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_equal_to cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_equal_to<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> == <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">==</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_equal_to</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">==</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_equal_to<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_equal_to<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>==
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>==
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_equal_to&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_equal_to</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>==
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> == <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_equal_to<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator == (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> == <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_equal_to<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_equal_to<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_greater</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_greater</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&gt;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_greater</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_greater.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_greater cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_greater<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> &gt; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&gt;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&gt;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_greater<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_greater<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&gt;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&gt;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_greater&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_greater</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&gt;
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> &gt; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &gt; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> &gt; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_greater_equal</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_greater_equal</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater_equal</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&gt;=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater_equal</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater_equal</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_greater_equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_greater_equal.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_greater_equal
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_greater_equal<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> &gt;= <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater_equal</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&gt;=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_greater_equal</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&gt;=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_greater_equal<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_greater_equal<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&gt;=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&gt;=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_greater_equal&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_greater_equal</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&gt;= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> &gt;= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater_equal<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &gt;= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> &gt;= <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater_equal<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_greater_equal<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -119,68 +119,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_left_shift</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_left_shift</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&lt;&lt;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_left_shift</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_left_shift.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_left_shift
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_left_shift<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> &lt;&lt; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&lt;&lt;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&lt;&lt;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_left_shift<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_left_shift<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_left_shift&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_left_shift</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt; or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> &lt;&lt; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &lt;&lt; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> &lt;&lt; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -107,68 +107,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_left_shift_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;&lt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&lt;&lt;=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;&lt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_left_shift_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_left_shift_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_left_shift_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_left_shift_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;&lt;=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> &lt;&lt;= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&lt;&lt;=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_left_shift_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&lt;&lt;=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_left_shift_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_left_shift_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt;=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt;=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_left_shift_assign&lt;Lhs&gt;</code>
will produce a compiler error. For this reason <code class="literal">has_left_shift_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&lt;&lt;= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> &lt;&lt;= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &lt;&lt;= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> &lt;&lt;= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_left_shift_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_less</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_less</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&lt;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_less</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_less.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_less cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_less<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> &lt; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&lt;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&lt;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_less<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_less<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&lt;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&lt;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_less&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_less</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&lt;
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> &lt; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_less<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &lt; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> &lt; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_less<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_less<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_less_equal</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_less_equal</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less_equal</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&lt;=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less_equal</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less_equal</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_less_equal</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_less_equal.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_less_equal
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_less_equal<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&lt;=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> &lt;= <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less_equal</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&lt;=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_less_equal</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&lt;=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_less_equal<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_less_equal<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&lt;=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&lt;=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_less_equal&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_less_equal</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&lt;= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> &lt;= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_less_equal<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &lt;= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> &lt;= <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_less_equal<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_less_equal<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -110,68 +110,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;&amp;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;&amp;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_logical_and</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_logical_and</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;&amp;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;&amp;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_and</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&amp;&amp;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&amp;&amp;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_and</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_and</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&amp;&amp;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_logical_and</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_logical_and.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_logical_and
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_logical_and<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&amp;&amp;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> &amp;&amp; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_and</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_and</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_logical_and<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_logical_and<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&amp;&amp;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&amp;&amp;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_logical_and&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_logical_and</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&amp;&amp; or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> &amp;&amp; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_and<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &amp;&amp; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> &amp;&amp; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_and<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_and<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -110,68 +110,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">||</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">||</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_logical_or</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_logical_or</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">||</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">||(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_or</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator||(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">||(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_or</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_or</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">||</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_logical_or</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_logical_or.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_logical_or
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_logical_or<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">||(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> || <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_or</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">||</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_logical_or</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">||</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_logical_or<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_logical_or<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>||
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>||
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_logical_or&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_logical_or</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>|| or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> || <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_or<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator || (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> || <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_or<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_logical_or<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,66 +113,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">-</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">-</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_minus</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_minus</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">-</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">-(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator-(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">-(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">-</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_minus</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_minus.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_minus cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_minus<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">-(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> - <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">-</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">-</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_minus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_minus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>-
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>-
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_minus&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_minus</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>-
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> - <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator - (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> - <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,68 +113,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">-=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">-=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_minus_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_minus_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">-=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator-=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">-=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_minus_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_minus_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_minus_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_minus_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> -= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">-=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_minus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">-=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_minus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_minus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>-=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>-=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_minus_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_minus_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>-= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> -= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator -= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> -= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_minus_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -106,66 +106,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">%</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">%</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_modulus</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_modulus</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">%</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">%(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator%(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">%(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">%</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_modulus</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_modulus.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_modulus cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_modulus<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">%(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> % <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">%</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">%</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_modulus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_modulus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>%
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>%
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_modulus&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_modulus</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>%
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> % <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator % (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> % <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -106,68 +106,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">%=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">%=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_modulus_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">%=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">%=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator%=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">%=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">%=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_modulus_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_modulus_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_modulus_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_modulus_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">%=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> %= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">%=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_modulus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">%=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_modulus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_modulus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>%=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>%=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_modulus_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_modulus_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>%= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> %= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator %= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> %= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_modulus_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,66 +113,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_multiplies</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_multiplies</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">*(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator*(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">*(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_multiplies</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_multiplies.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_multiplies
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_multiplies<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">*(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> * <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">*</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">*</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_multiplies<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_multiplies<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>*
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>*
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_multiplies&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_multiplies</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>* or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> * <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator * (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> * <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,68 +113,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">*=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">*=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_multiplies_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">*=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">*=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator*=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">*=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">*=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_multiplies_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_multiplies_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_multiplies_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_multiplies_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">*=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> *= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">*=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_multiplies_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">*=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_multiplies_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_multiplies_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>*=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>*=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_multiplies_assign&lt;Lhs&gt;</code>
will produce a compiler error. For this reason <code class="literal">has_multiplies_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>*= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> *= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator *= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> *= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_multiplies_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -112,68 +112,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">!=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">!=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_not_equal_to</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">!=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator!=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">!=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_not_equal_to</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_not_equal_to.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_not_equal_to
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_not_equal_to<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
bool <span class="keyword">operator</span> != <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">!=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_not_equal_to</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">!=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_not_equal_to<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_not_equal_to<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>!=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>!=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_not_equal_to&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_not_equal_to</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>!= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> bool <span class="keyword">operator</span> != <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_not_equal_to<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator != (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
bool <span class="keyword">operator</span> != <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_not_equal_to<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_not_equal_to<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,66 +113,82 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">+</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">+</span></code> is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code> then instantiating <code class="computeroutput"><span class="identifier">has_plus</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code>
will produce a compiler error. For this reason <code class="computeroutput"><span class="identifier">has_plus</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">+</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator+(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">+</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_plus</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_plus.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_plus cannot
perform introspection of the template function body to ensure that the type
meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_plus<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> + <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">+</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">+</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_plus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_plus<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>+
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>+
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_plus&lt;Lhs&gt;</code> will produce
a compiler error. For this reason <code class="literal">has_plus</code> cannot
be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>+
or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> + <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator + (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> + <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -113,68 +113,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">+=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">+=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_plus_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_plus_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">+=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator+=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">+=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_plus_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_plus_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_plus_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_plus_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> += <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">+=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_plus_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">+=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_plus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_plus_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>+=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>+=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_plus_assign&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_plus_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>+= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> += <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator += (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> += <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_plus_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -119,68 +119,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_right_shift</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_right_shift</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&gt;&gt;(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_right_shift</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_right_shift.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_right_shift
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_right_shift<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt; <span class="keyword">operator</span> &gt;&gt; <span class="special">(</span>const <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&gt;&gt;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&gt;&gt;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_right_shift<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_right_shift<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt;
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt;
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_right_shift&lt;Lhs&gt;</code> will
produce a compiler error. For this reason <code class="literal">has_right_shift</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt; or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A <span class="keyword">operator</span> &gt;&gt; <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &gt;&gt; (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A <span class="keyword">operator</span> &gt;&gt; <span class="special">(</span>const <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -111,68 +111,81 @@
<p>
<span class="bold"><strong>Known issues:</strong></span>
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;=</span></code> is public or not: if <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;=</span></code>
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="computeroutput"><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span><span class="identifier">Lhs</span><span class="special">&gt;</span></code> will produce a compiler error. For
this reason <code class="computeroutput"><span class="identifier">has_right_shift_assign</span></code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;=</span></code>
or not.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator&gt;&gt;=(const A&amp;) is private</span>
</pre>
</li>
<li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;=(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
</li>
<li class="listitem">
There is an issue when applying this trait to template classes. If <code class="computeroutput"><span class="keyword">operator</span><span class="special">&gt;&gt;=</span></code>
is defined but does not bind for a given template type, it is still detected
by the trait which returns <code class="computeroutput"><span class="keyword">true</span></code>
instead of <code class="computeroutput"><span class="keyword">false</span></code>. Example:
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">has_right_shift_assign</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<p>
For modern compilers (those that support arbitrary SFINAE-expressions and
decltype/declval) this trait offers near perfect detection. In this situation
the macro <code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
will be defined after including <code class="literal">&lt;boost/type_traits/has_right_shift_assign.hpp&gt;</code>.
Please note however, that detection is based on function signature only,
in the case that the operator is a function template then has_right_shift_assign
cannot perform introspection of the template function body to ensure that
the type meets all of the conceptual requirements of the actual code.
</p>
<p>
Example:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">type_traits</span><span class="special">/</span>has_right_shift_assign<span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">contains</span> <span class="special">{</span> <span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">contains</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">contains</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">d</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">data</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span> <span class="special">{}</span>
<span class="special">};</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">&gt;&gt;=(</span><span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
contains&lt;T&gt;&amp; <span class="keyword">operator</span> &gt;&gt;= <span class="special">(</span><span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">.</span><span class="identifier">data</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">class</span> <span class="identifier">bad</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">class</span> <span class="identifier">good</span> <span class="special">{</span> <span class="special">};</span>
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="special">}</span>
<span class="identifier">good</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">good</span><span class="special">&amp;)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="comment">/*something*/</span><span class="special">;</span> <span class="special">}</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span> <span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&gt;&gt;=</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">has_right_shift_assign</span><span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&gt;&gt;=</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">boolalpha</span><span class="special">;</span>
<span class="comment">// works fine for contains&lt;good&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_right_shift_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">good</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">good</span><span class="special">&gt;</span> <span class="identifier">g</span><span class="special">;</span>
<span class="identifier">g</span><span class="special">&amp;</span><span class="identifier">g</span><span class="special">;</span> <span class="comment">// ok</span>
<span class="comment">// does not work for contains&lt;bad&gt;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span><span class="special">&lt;&lt;</span><span class="identifier">boost</span><span class="special">::</span>has_right_shift_assign<span class="special">&lt;</span> <span class="identifier">contains</span><span class="special">&lt;</span> <span class="identifier">bad</span> <span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">value</span><span class="special">&lt;&lt;</span><span class="char">'\n'</span><span class="special">;</span> <span class="comment">// true, should be false</span>
<span class="identifier">contains</span><span class="special">&lt;</span><span class="identifier">bad</span><span class="special">&gt;</span> <span class="identifier">b</span><span class="special">;</span>
<span class="identifier">b</span><span class="special">&amp;</span><span class="identifier">b</span><span class="special">;</span> <span class="comment">// compile time error</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</li>
<li class="listitem">
<p>
For older compilers (<code class="computeroutput"><span class="identifier">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></code>
not defined) then there are a number of issues:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
This trait cannot detect whether binary <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt;=
is public or not: if <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt;=
is defined as a private member of <code class="computeroutput"><span class="identifier">Lhs</span></code>
then instantiating <code class="literal">has_right_shift_assign&lt;Lhs&gt;</code>
will produce a compiler error. For this reason <code class="literal">has_right_shift_assign</code>
cannot be used to determine whether a type has a public <code class="computeroutput"><span class="keyword">operator</span></code>&gt;&gt;= or not.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="keyword">private</span><span class="special">:</span> A&amp; <span class="keyword">operator</span> &gt;&gt;= <span class="special">(</span><span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: A::operator &gt;&gt;= (const A&amp;) is private</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
There is an issue if the operator exists only for type <code class="computeroutput"><span class="identifier">A</span></code> and <code class="computeroutput"><span class="identifier">B</span></code>
is convertible to <code class="computeroutput"><span class="identifier">A</span></code>.
In this case, the compiler will report an ambiguous overload.
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">A</span> <span class="special">{</span> <span class="special">};</span>
A&amp; <span class="keyword">operator</span> &gt;&gt;= <span class="special">(</span><span class="identifier">A</span><span class="special">&amp;,</span> <span class="keyword">const</span> <span class="identifier">A</span><span class="special">&amp;);</span>
<span class="keyword">struct</span> <span class="identifier">B</span> <span class="special">{</span> <span class="keyword">operator</span> <span class="identifier">A</span><span class="special">();</span> <span class="special">};</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift_assign<span class="special">&lt;</span><span class="identifier">A</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// this is fine</span>
<span class="identifier">boost</span><span class="special">::</span>has_right_shift_assign<span class="special">&lt;</span><span class="identifier">B</span><span class="special">&gt;::</span><span class="identifier">value</span><span class="special">;</span> <span class="comment">// error: ambiguous overload</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<code class="computeroutput"><span class="keyword">volatile</span></code> qualifier is not
properly handled and would lead to undefined behavior
</li>
</ul></div>
</li></ul></div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>

View File

@ -24,7 +24,7 @@
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="id1670677"></a>Class Index</h2></div></div></div>
<a name="id1658358"></a>Class Index</h2></div></div></div>
<p><a class="link" href="s11.html#idx_id_0">A</a> <a class="link" href="s11.html#idx_id_2">C</a> <a class="link" href="s11.html#idx_id_3">D</a> <a class="link" href="s11.html#idx_id_4">E</a> <a class="link" href="s11.html#idx_id_5">F</a> <a class="link" href="s11.html#idx_id_6">H</a> <a class="link" href="s11.html#idx_id_7">I</a> <a class="link" href="s11.html#idx_id_8">M</a> <a class="link" href="s11.html#idx_id_9">N</a> <a class="link" href="s11.html#idx_id_10">O</a> <a class="link" href="s11.html#idx_id_11">P</a> <a class="link" href="s11.html#idx_id_12">R</a> <a class="link" href="s11.html#idx_id_13">T</a></p>
<div class="variablelist"><dl class="variablelist">
<dt>
@ -358,42 +358,14 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">trait</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">has_bit_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">has_bit_and_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">has_bit_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">has_bit_or_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">has_bit_xor</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">has_bit_xor_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_complement.html" title="has_complement"><span class="index-entry-level-1">has_complement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_dereference.html" title="has_dereference"><span class="index-entry-level-1">has_dereference</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">has_divides</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">has_divides_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">has_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">has_greater</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">has_greater_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">has_left_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">has_left_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">has_less</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">has_less_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">has_logical_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_not.html" title="has_logical_not"><span class="index-entry-level-1">has_logical_not</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">has_logical_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">has_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">has_minus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">has_modulus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">has_modulus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">has_multiplies</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">has_multiplies_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_negate.html" title="has_negate"><span class="index-entry-level-1">has_negate</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">has_not_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">has_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">has_plus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_post_decrement.html" title="has_post_decrement"><span class="index-entry-level-1">has_post_decrement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_post_increment.html" title="has_post_increment"><span class="index-entry-level-1">has_post_increment</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_pre_decrement.html" title="has_pre_decrement"><span class="index-entry-level-1">has_pre_decrement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_pre_increment.html" title="has_pre_increment"><span class="index-entry-level-1">has_pre_increment</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">has_right_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">has_right_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_unary_minus.html" title="has_unary_minus"><span class="index-entry-level-1">has_unary_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_unary_plus.html" title="has_unary_plus"><span class="index-entry-level-1">has_unary_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/category/value_traits/operators.html" title="Operator Type Traits"><span class="index-entry-level-1">Operator Type Traits</span></a></p></li>

View File

@ -24,7 +24,7 @@
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="id1672702"></a>Typedef Index</h2></div></div></div>
<a name="id1662618"></a>Typedef Index</h2></div></div></div>
<p><a class="link" href="s12.html#idx_id_21">F</a> <a class="link" href="s12.html#idx_id_28">R</a> <a class="link" href="s12.html#idx_id_29">T</a> <a class="link" href="s12.html#idx_id_31">V</a></p>
<div class="variablelist"><dl class="variablelist">
<dt>

View File

@ -24,7 +24,7 @@
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="id1672913"></a>Macro Index</h2></div></div></div>
<a name="id1662800"></a>Macro Index</h2></div></div></div>
<p><a class="link" href="s13.html#idx_id_33">B</a></p>
<div class="variablelist"><dl class="variablelist">
<dt>
@ -164,6 +164,39 @@
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">has_bit_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">has_bit_and_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">has_bit_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">has_bit_or_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">has_bit_xor</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">has_bit_xor_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">has_divides</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">has_divides_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">has_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">has_greater</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">has_greater_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">has_left_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">has_left_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">has_less</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">has_less_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">has_logical_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">has_logical_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">has_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">has_minus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">has_modulus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">has_modulus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">has_multiplies</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">has_multiplies_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">has_not_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">has_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">has_plus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">has_right_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">has_right_shift_assign</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION</span></p>
<div class="index"><ul class="index" style="list-style-type: none; "><li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/is_class.html" title="is_class"><span class="index-entry-level-1">is_class</span></a></p></li></ul></div>
</li>

View File

@ -23,7 +23,7 @@
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="id1673613"></a>Index</h2></div></div></div>
<a name="id1661483"></a>Index</h2></div></div></div>
<p><a class="link" href="s14.html#idx_id_48">A</a> <a class="link" href="s14.html#idx_id_49">B</a> <a class="link" href="s14.html#idx_id_50">C</a> <a class="link" href="s14.html#idx_id_51">D</a> <a class="link" href="s14.html#idx_id_52">E</a> <a class="link" href="s14.html#idx_id_53">F</a> <a class="link" href="s14.html#idx_id_54">H</a> <a class="link" href="s14.html#idx_id_55">I</a> <a class="link" href="s14.html#idx_id_56">M</a> <a class="link" href="s14.html#idx_id_57">N</a> <a class="link" href="s14.html#idx_id_58">O</a> <a class="link" href="s14.html#idx_id_59">P</a> <a class="link" href="s14.html#idx_id_60">R</a> <a class="link" href="s14.html#idx_id_61">T</a> <a class="link" href="s14.html#idx_id_62">U</a> <a class="link" href="s14.html#idx_id_63">V</a></p>
<div class="variablelist"><dl class="variablelist">
<dt>
@ -195,6 +195,39 @@
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">has_bit_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">has_bit_and_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">has_bit_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">has_bit_or_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">has_bit_xor</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">has_bit_xor_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">has_divides</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">has_divides_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">has_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">has_greater</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">has_greater_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">has_left_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">has_left_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">has_less</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">has_less_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">has_logical_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">has_logical_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">has_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">has_minus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">has_modulus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">has_modulus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">has_multiplies</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">has_multiplies_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">has_not_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">has_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">has_plus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">has_right_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">has_right_shift_assign</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION</span></p>
<div class="index"><ul class="index" style="list-style-type: none; "><li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/is_class.html" title="is_class"><span class="index-entry-level-1">is_class</span></a></p></li></ul></div>
</li>
@ -308,49 +341,49 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_and</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">has_bit_and</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_and_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">has_bit_and_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_or</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">has_bit_or</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_or_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">has_bit_or_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_xor</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">has_bit_xor</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_bit_xor_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">has_bit_xor_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -372,82 +405,82 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_divides</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">has_divides</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_divides_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">has_divides_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_equal_to</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">has_equal_to</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/category/value_traits/operators.html" title="Operator Type Traits"><span class="index-entry-level-1">Operator Type Traits</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_greater</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">has_greater</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_greater_equal</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">has_greater_equal</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_left_shift</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">has_left_shift</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_left_shift_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">has_left_shift_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_less</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">has_less</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_less_equal</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">has_less_equal</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_logical_and</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">has_logical_and</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -461,57 +494,57 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_logical_or</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">has_logical_or</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_minus</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">has_minus</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_minus_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">has_minus_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_modulus</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">has_modulus</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_modulus_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">has_modulus_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_multiplies</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">has_multiplies</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_multiplies_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">has_multiplies_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -558,9 +591,9 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_not_equal_to</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">has_not_equal_to</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -570,17 +603,17 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_plus</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">has_plus</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_plus_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">has_plus_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -618,17 +651,17 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_right_shift</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">has_right_shift</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">has_right_shift_assign</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">dont_care</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><span class="bold"><strong><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">has_right_shift_assign</span></a></strong></span></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">trait</span></a></p></li>
</ul></div>
</li>
<li class="listitem" style="list-style-type: none">
@ -982,42 +1015,14 @@
<li class="listitem" style="list-style-type: none">
<p><span class="index-entry-level-0">trait</span></p>
<div class="index"><ul class="index" style="list-style-type: none; ">
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and.html" title="has_bit_and"><span class="index-entry-level-1">has_bit_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_and_assign.html" title="has_bit_and_assign"><span class="index-entry-level-1">has_bit_and_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or.html" title="has_bit_or"><span class="index-entry-level-1">has_bit_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_or_assign.html" title="has_bit_or_assign"><span class="index-entry-level-1">has_bit_or_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor.html" title="has_bit_xor"><span class="index-entry-level-1">has_bit_xor</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_bit_xor_assign.html" title="has_bit_xor_assign"><span class="index-entry-level-1">has_bit_xor_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_complement.html" title="has_complement"><span class="index-entry-level-1">has_complement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_dereference.html" title="has_dereference"><span class="index-entry-level-1">has_dereference</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides.html" title="has_divides"><span class="index-entry-level-1">has_divides</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_divides_assign.html" title="has_divides_assign"><span class="index-entry-level-1">has_divides_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_equal_to.html" title="has_equal_to"><span class="index-entry-level-1">has_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater.html" title="has_greater"><span class="index-entry-level-1">has_greater</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_greater_equal.html" title="has_greater_equal"><span class="index-entry-level-1">has_greater_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift.html" title="has_left_shift"><span class="index-entry-level-1">has_left_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_left_shift_assign.html" title="has_left_shift_assign"><span class="index-entry-level-1">has_left_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less.html" title="has_less"><span class="index-entry-level-1">has_less</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_less_equal.html" title="has_less_equal"><span class="index-entry-level-1">has_less_equal</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_and.html" title="has_logical_and"><span class="index-entry-level-1">has_logical_and</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_not.html" title="has_logical_not"><span class="index-entry-level-1">has_logical_not</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_logical_or.html" title="has_logical_or"><span class="index-entry-level-1">has_logical_or</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus.html" title="has_minus"><span class="index-entry-level-1">has_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_minus_assign.html" title="has_minus_assign"><span class="index-entry-level-1">has_minus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus.html" title="has_modulus"><span class="index-entry-level-1">has_modulus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_modulus_assign.html" title="has_modulus_assign"><span class="index-entry-level-1">has_modulus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies.html" title="has_multiplies"><span class="index-entry-level-1">has_multiplies</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_multiplies_assign.html" title="has_multiplies_assign"><span class="index-entry-level-1">has_multiplies_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_negate.html" title="has_negate"><span class="index-entry-level-1">has_negate</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_not_equal_to.html" title="has_not_equal_to"><span class="index-entry-level-1">has_not_equal_to</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus.html" title="has_plus"><span class="index-entry-level-1">has_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_plus_assign.html" title="has_plus_assign"><span class="index-entry-level-1">has_plus_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_post_decrement.html" title="has_post_decrement"><span class="index-entry-level-1">has_post_decrement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_post_increment.html" title="has_post_increment"><span class="index-entry-level-1">has_post_increment</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_pre_decrement.html" title="has_pre_decrement"><span class="index-entry-level-1">has_pre_decrement</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_pre_increment.html" title="has_pre_increment"><span class="index-entry-level-1">has_pre_increment</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift.html" title="has_right_shift"><span class="index-entry-level-1">has_right_shift</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_right_shift_assign.html" title="has_right_shift_assign"><span class="index-entry-level-1">has_right_shift_assign</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_unary_minus.html" title="has_unary_minus"><span class="index-entry-level-1">has_unary_minus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/reference/has_unary_plus.html" title="has_unary_plus"><span class="index-entry-level-1">has_unary_plus</span></a></p></li>
<li class="listitem" style="list-style-type: none"><p><a class="link" href="../boost_typetraits/category/value_traits/operators.html" title="Operator Type Traits"><span class="index-entry-level-1">Operator Type Traits</span></a></p></li>

View File

@ -158,6 +158,74 @@
[template all_compilers[] __compat All current compilers are supported by this trait.]
[template has_binary_operator_compat[] __compat Requires working SFINAE (i.e. BOOST_NO_SFINAE is not set). Only a minority of rather old compilers do not support this.]
[template binary_operator_known_issues[Name Op Ret1 Ret2 Const]
[*Known issues:]
For modern compilers (those that support arbitrary SFINAE-expressions and decltype/declval) this trait offers near perfect detection.
In this situation the macro `BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION` will be defined after including
[^<boost/type_traits/[Name].hpp>]. Please note however, that detection is based on function signature only,
in the case that the operator is a function template then [Name] cannot perform
introspection of the template function body to ensure that the type meets all of the conceptual requirements of the actual code.
Example:
#include <boost/type_traits/``[Name]``.hpp>
#include <iostream>
template <class T>
struct contains
{
T data;
contains(const T& d) : data(d) {}
};
template <class T>
``[Ret2]`` operator ``[Op]`` (``[Const]``contains<T> &lhs, const contains<T> &rhs) {
return f(lhs.data, rhs.data);
}
class bad { };
class good { };
good f(const good&, const good&) { return /*something*/; }
int main() {
std::cout<<std::boolalpha;
// works fine for contains<good>
std::cout<<boost::``[Name]``< contains< good > >::value<<'\n'; // true
contains<good> g;
g&g; // ok
// does not work for contains<bad>
std::cout<<boost::``[Name]``< contains< bad > >::value<<'\n'; // true, should be false
contains<bad> b;
b&b; // compile time error
return 0;
}
For older compilers (`BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION` not defined) then there are a number of issues:
* This trait cannot detect whether binary `operator`[Op] is public or not:
if `operator`[Op] is defined as a private member of `Lhs` then
instantiating [^[Name]<Lhs>] will produce a compiler error.
For this reason [^[Name]] cannot be used to determine whether a type has a public `operator`[Op] or not.
struct A { private: ``[Ret1]`` operator ``[Op]`` (const A&); };
boost::``[Name]``<A>::value; // error: A::operator ``[Op]`` (const A&) 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 { };
``[Ret1]`` operator ``[Op]`` (``[Const]``A&, const A&);
struct B { operator A(); };
boost::``[Name]``<A>::value; // this is fine
boost::``[Name]``<B>::value; // error: ambiguous overload
* `volatile` qualifier is not properly handled and would lead to undefined behavior
]
A printer-friendly [@http://sourceforge.net/projects/boost/files/boost-docs/
PDF version of this manual is also available].