// DR 339 // // Test of the use of various boolean binary operators with SFINAE // Boilerplate helpers typedef char yes_type; struct no_type { char data[2]; }; template T create_a(); template struct type { }; template struct enable_if { typedef T type; }; template struct enable_if { }; #define JOIN( X, Y ) DO_JOIN( X, Y ) #define DO_JOIN( X, Y ) DO_JOIN2(X,Y) #define DO_JOIN2( X, Y ) X##Y bool accepts_bool(bool); #define DEFINE_BINARY_PREDICATE_TRAIT(Name,Op) \ template \ typename enable_if() Op create_a())), \ yes_type>::type \ JOIN(check_,Name)(type, type); \ \ no_type JOIN(check_,Name)(...); \ \ template \ struct Name \ { \ static const bool value = \ (sizeof(JOIN(check_,Name)(type(), type())) == sizeof(yes_type)); \ } #ifdef __GXX_EXPERIMENTAL_CXX0X__ # define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) #else # define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] #endif struct X { }; struct Y { }; struct convertible_to_bool { operator int convertible_to_bool::* (); }; struct not_convertible_to_bool { }; // is_less_than_comparable DEFINE_BINARY_PREDICATE_TRAIT(is_less_than_comparable,<); bool operator<(X, X); convertible_to_bool operator<(X, Y); not_convertible_to_bool operator<(Y, X); STATIC_ASSERT((is_less_than_comparable::value)); STATIC_ASSERT((is_less_than_comparable::value)); STATIC_ASSERT((is_less_than_comparable::value)); STATIC_ASSERT((is_less_than_comparable::value)); STATIC_ASSERT((is_less_than_comparable::value)); STATIC_ASSERT((!is_less_than_comparable::value)); STATIC_ASSERT((!is_less_than_comparable::value)); // is_less_equal_comparable DEFINE_BINARY_PREDICATE_TRAIT(is_less_equal_comparable,<=); bool operator<=(X, X); convertible_to_bool operator<=(X, Y); not_convertible_to_bool operator<=(Y, X); STATIC_ASSERT((is_less_equal_comparable::value)); STATIC_ASSERT((is_less_equal_comparable::value)); STATIC_ASSERT((is_less_equal_comparable::value)); STATIC_ASSERT((is_less_equal_comparable::value)); STATIC_ASSERT((is_less_equal_comparable::value)); STATIC_ASSERT((!is_less_equal_comparable::value)); STATIC_ASSERT((!is_less_equal_comparable::value)); // is_greater_than_comparable DEFINE_BINARY_PREDICATE_TRAIT(is_greater_than_comparable,>); bool operator>(X, X); convertible_to_bool operator>(X, Y); not_convertible_to_bool operator>(Y, X); STATIC_ASSERT((is_greater_than_comparable::value)); STATIC_ASSERT((is_greater_than_comparable::value)); STATIC_ASSERT((is_greater_than_comparable::value)); STATIC_ASSERT((is_greater_than_comparable::value)); STATIC_ASSERT((is_greater_than_comparable::value)); STATIC_ASSERT((!is_greater_than_comparable::value)); STATIC_ASSERT((!is_greater_than_comparable::value)); // is_greater_equal_comparable DEFINE_BINARY_PREDICATE_TRAIT(is_greater_equal_comparable,>=); bool operator>=(X, X); convertible_to_bool operator>=(X, Y); not_convertible_to_bool operator>=(Y, X); STATIC_ASSERT((is_greater_equal_comparable::value)); STATIC_ASSERT((is_greater_equal_comparable::value)); STATIC_ASSERT((is_greater_equal_comparable::value)); STATIC_ASSERT((is_greater_equal_comparable::value)); STATIC_ASSERT((is_greater_equal_comparable::value)); STATIC_ASSERT((!is_greater_equal_comparable::value)); STATIC_ASSERT((!is_greater_equal_comparable::value)); // is_equality_comparable struct Z : X { }; DEFINE_BINARY_PREDICATE_TRAIT(is_equality_comparable,==); bool operator==(X, X); convertible_to_bool operator==(X, Y); not_convertible_to_bool operator==(Y, X); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((!is_equality_comparable::value)); STATIC_ASSERT((!is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((!is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((is_equality_comparable::value)); STATIC_ASSERT((!is_equality_comparable::value)); // is_not_equal_comparable DEFINE_BINARY_PREDICATE_TRAIT(is_not_equal_comparable,!=); bool operator!=(X, X); convertible_to_bool operator!=(X, Y); not_convertible_to_bool operator!=(Y, X); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((!is_not_equal_comparable::value)); STATIC_ASSERT((!is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((!is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((is_not_equal_comparable::value)); STATIC_ASSERT((!is_not_equal_comparable::value)); // has_logical_and DEFINE_BINARY_PREDICATE_TRAIT(has_logical_and,&&); bool operator&&(X, X); convertible_to_bool operator&&(X, Y); not_convertible_to_bool operator&&(Y, X); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((!has_logical_and::value)); STATIC_ASSERT((!has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); STATIC_ASSERT((has_logical_and::value)); // has_logical_or DEFINE_BINARY_PREDICATE_TRAIT(has_logical_or,||); bool operator||(X, X); convertible_to_bool operator||(X, Y); not_convertible_to_bool operator||(Y, X); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((!has_logical_or::value)); STATIC_ASSERT((!has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value)); STATIC_ASSERT((has_logical_or::value));