1 // DR 339 2 // 3 // Test of the use of various boolean binary operators with SFINAE 4 5 // Boilerplate helpers 6 typedef char yes_type; 7 struct no_type { char data[2]; }; 8 9 template<typename T> T create_a(); 10 template<typename T> struct type { }; 11 12 template<bool, typename T = void> struct enable_if { typedef T type; }; 13 template<typename T> struct enable_if<false, T> { }; 14 15 #define JOIN( X, Y ) DO_JOIN( X, Y ) 16 #define DO_JOIN( X, Y ) DO_JOIN2(X,Y) 17 #define DO_JOIN2( X, Y ) X##Y 18 19 bool accepts_bool(bool); 20 21 #define DEFINE_BINARY_PREDICATE_TRAIT(Name,Op) \ 22 template<typename T, typename U> \ 23 typename enable_if<sizeof(accepts_bool(create_a<T>() Op create_a<U>())), \ 24 yes_type>::type \ 25 JOIN(check_,Name)(type<T>, type<U>); \ 26 \ 27 no_type JOIN(check_,Name)(...); \ 28 \ 29 template<typename T, typename U = T> \ 30 struct Name \ 31 { \ 32 static const bool value = \ 33 (sizeof(JOIN(check_,Name)(type<T>(), type<U>())) == sizeof(yes_type)); \ 34 } 35 36 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 37 # define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) 38 #else 39 # define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] 40 #endif 41 42 struct X { }; 43 struct Y { }; 44 45 struct convertible_to_bool { 46 operator int convertible_to_bool::* (); 47 }; 48 49 struct not_convertible_to_bool { }; 50 51 // is_less_than_comparable 52 DEFINE_BINARY_PREDICATE_TRAIT(is_less_than_comparable,<); 53 bool operator<(X, X); 54 convertible_to_bool operator<(X, Y); 55 not_convertible_to_bool operator<(Y, X); 56 57 STATIC_ASSERT((is_less_than_comparable<int>::value)); 58 STATIC_ASSERT((is_less_than_comparable<int, long>::value)); 59 STATIC_ASSERT((is_less_than_comparable<int*>::value)); 60 STATIC_ASSERT((is_less_than_comparable<X>::value)); 61 STATIC_ASSERT((is_less_than_comparable<X, Y>::value)); 62 STATIC_ASSERT((!is_less_than_comparable<Y, X>::value)); 63 STATIC_ASSERT((!is_less_than_comparable<Y>::value)); 64 65 // is_less_equal_comparable 66 DEFINE_BINARY_PREDICATE_TRAIT(is_less_equal_comparable,<=); 67 bool operator<=(X, X); 68 convertible_to_bool operator<=(X, Y); 69 not_convertible_to_bool operator<=(Y, X); 70 71 STATIC_ASSERT((is_less_equal_comparable<int>::value)); 72 STATIC_ASSERT((is_less_equal_comparable<int, long>::value)); 73 STATIC_ASSERT((is_less_equal_comparable<int*>::value)); 74 STATIC_ASSERT((is_less_equal_comparable<X>::value)); 75 STATIC_ASSERT((is_less_equal_comparable<X, Y>::value)); 76 STATIC_ASSERT((!is_less_equal_comparable<Y, X>::value)); 77 STATIC_ASSERT((!is_less_equal_comparable<Y>::value)); 78 79 // is_greater_than_comparable 80 DEFINE_BINARY_PREDICATE_TRAIT(is_greater_than_comparable,>); 81 bool operator>(X, X); 82 convertible_to_bool operator>(X, Y); 83 not_convertible_to_bool operator>(Y, X); 84 85 STATIC_ASSERT((is_greater_than_comparable<int>::value)); 86 STATIC_ASSERT((is_greater_than_comparable<int, long>::value)); 87 STATIC_ASSERT((is_greater_than_comparable<int*>::value)); 88 STATIC_ASSERT((is_greater_than_comparable<X>::value)); 89 STATIC_ASSERT((is_greater_than_comparable<X, Y>::value)); 90 STATIC_ASSERT((!is_greater_than_comparable<Y, X>::value)); 91 STATIC_ASSERT((!is_greater_than_comparable<Y>::value)); 92 93 // is_greater_equal_comparable 94 DEFINE_BINARY_PREDICATE_TRAIT(is_greater_equal_comparable,>=); 95 bool operator>=(X, X); 96 convertible_to_bool operator>=(X, Y); 97 not_convertible_to_bool operator>=(Y, X); 98 99 STATIC_ASSERT((is_greater_equal_comparable<int>::value)); 100 STATIC_ASSERT((is_greater_equal_comparable<int, long>::value)); 101 STATIC_ASSERT((is_greater_equal_comparable<int*>::value)); 102 STATIC_ASSERT((is_greater_equal_comparable<X>::value)); 103 STATIC_ASSERT((is_greater_equal_comparable<X, Y>::value)); 104 STATIC_ASSERT((!is_greater_equal_comparable<Y, X>::value)); 105 STATIC_ASSERT((!is_greater_equal_comparable<Y>::value)); 106 107 // is_equality_comparable 108 struct Z : X { }; 109 DEFINE_BINARY_PREDICATE_TRAIT(is_equality_comparable,==); 110 bool operator==(X, X); 111 convertible_to_bool operator==(X, Y); 112 not_convertible_to_bool operator==(Y, X); 113 114 STATIC_ASSERT((is_equality_comparable<int>::value)); 115 STATIC_ASSERT((is_equality_comparable<int, long>::value)); 116 STATIC_ASSERT((is_equality_comparable<int*>::value)); 117 STATIC_ASSERT((is_equality_comparable<X>::value)); 118 STATIC_ASSERT((is_equality_comparable<X, Y>::value)); 119 STATIC_ASSERT((!is_equality_comparable<Y, X>::value)); 120 STATIC_ASSERT((!is_equality_comparable<Y>::value)); 121 STATIC_ASSERT((is_equality_comparable<int X::*>::value)); 122 STATIC_ASSERT((!is_equality_comparable<int X::*, int Y::*>::value)); 123 STATIC_ASSERT((!is_equality_comparable<int*, float*>::value)); 124 STATIC_ASSERT((is_equality_comparable<X*, Z*>::value)); 125 STATIC_ASSERT((!is_equality_comparable<X*, Y*>::value)); 126 127 // is_not_equal_comparable 128 DEFINE_BINARY_PREDICATE_TRAIT(is_not_equal_comparable,!=); 129 bool operator!=(X, X); 130 convertible_to_bool operator!=(X, Y); 131 not_convertible_to_bool operator!=(Y, X); 132 133 STATIC_ASSERT((is_not_equal_comparable<int>::value)); 134 STATIC_ASSERT((is_not_equal_comparable<int, long>::value)); 135 STATIC_ASSERT((is_not_equal_comparable<int*>::value)); 136 STATIC_ASSERT((is_not_equal_comparable<X>::value)); 137 STATIC_ASSERT((is_not_equal_comparable<X, Y>::value)); 138 STATIC_ASSERT((!is_not_equal_comparable<Y, X>::value)); 139 STATIC_ASSERT((!is_not_equal_comparable<Y>::value)); 140 STATIC_ASSERT((is_not_equal_comparable<int X::*>::value)); 141 STATIC_ASSERT((!is_not_equal_comparable<int X::*, int Y::*>::value)); 142 STATIC_ASSERT((!is_not_equal_comparable<int*, float*>::value)); 143 STATIC_ASSERT((is_not_equal_comparable<X*, Z*>::value)); 144 STATIC_ASSERT((!is_not_equal_comparable<X*, Y*>::value)); 145 146 // has_logical_and 147 DEFINE_BINARY_PREDICATE_TRAIT(has_logical_and,&&); 148 bool operator&&(X, X); 149 convertible_to_bool operator&&(X, Y); 150 not_convertible_to_bool operator&&(Y, X); 151 152 STATIC_ASSERT((has_logical_and<int>::value)); 153 STATIC_ASSERT((has_logical_and<int, long>::value)); 154 STATIC_ASSERT((has_logical_and<int*>::value)); 155 STATIC_ASSERT((has_logical_and<X>::value)); 156 STATIC_ASSERT((has_logical_and<X, Y>::value)); 157 STATIC_ASSERT((!has_logical_and<Y, X>::value)); 158 STATIC_ASSERT((!has_logical_and<Y>::value)); 159 STATIC_ASSERT((has_logical_and<int X::*>::value)); 160 STATIC_ASSERT((has_logical_and<int X::*, int Y::*>::value)); 161 STATIC_ASSERT((has_logical_and<int*, float*>::value)); 162 STATIC_ASSERT((has_logical_and<X*, Z*>::value)); 163 STATIC_ASSERT((has_logical_and<X*, Y*>::value)); 164 165 // has_logical_or 166 DEFINE_BINARY_PREDICATE_TRAIT(has_logical_or,||); 167 bool operator||(X, X); 168 convertible_to_bool operator||(X, Y); 169 not_convertible_to_bool operator||(Y, X); 170 171 STATIC_ASSERT((has_logical_or<int>::value)); 172 STATIC_ASSERT((has_logical_or<int, long>::value)); 173 STATIC_ASSERT((has_logical_or<int*>::value)); 174 STATIC_ASSERT((has_logical_or<X>::value)); 175 STATIC_ASSERT((has_logical_or<X, Y>::value)); 176 STATIC_ASSERT((!has_logical_or<Y, X>::value)); 177 STATIC_ASSERT((!has_logical_or<Y>::value)); 178 STATIC_ASSERT((has_logical_or<int X::*>::value)); 179 STATIC_ASSERT((has_logical_or<int X::*, int Y::*>::value)); 180 STATIC_ASSERT((has_logical_or<int*, float*>::value)); 181 STATIC_ASSERT((has_logical_or<X*, Z*>::value)); 182 STATIC_ASSERT((has_logical_or<X*, Y*>::value)); 183