1// DR 339 2// 3// Test of the use of various assignment operators with SFINAE 4 5// Boilerplate helpers 6typedef char yes_type; 7struct no_type { char data[2]; }; 8 9template<typename T> T create_a(); 10template<typename T> struct type { }; 11 12template<bool, typename T = void> struct enable_if { typedef T type; }; 13template<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#define DEFINE_INFIX_BINARY_TRAIT(Name,Op) \ 20template<typename T, typename U> \ 21 typename enable_if<(sizeof(create_a<T>() Op create_a<U>(), 1) > 0), \ 22 yes_type>::type \ 23 JOIN(check_,Name)(type<T>, type<U>); \ 24 \ 25no_type JOIN(check_,Name)(...); \ 26 \ 27template<typename T, typename U = T> \ 28struct Name \ 29{ \ 30 static const bool value = \ 31 (sizeof(JOIN(check_,Name)(type<T&>(), type<U>())) == sizeof(yes_type)); \ 32} 33 34#ifdef __GXX_EXPERIMENTAL_CXX0X__ 35# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) 36#else 37# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] 38#endif 39 40struct Y { 41 Y& operator=(Y&); 42}; 43 44struct X { 45 X& operator=(Y); 46 X& operator+=(X); 47 X& operator-=(X); 48 X& operator*=(X); 49 X& operator/=(X); 50 X& operator%=(X); 51 X& operator^=(X); 52 X& operator&=(X); 53 X& operator|=(X); 54 X& operator<<=(X); 55 X& operator>>=(X); 56}; 57struct Z { }; 58 59// is_assignable 60DEFINE_INFIX_BINARY_TRAIT(is_assignable, =); 61STATIC_ASSERT((is_assignable<int>::value)); 62STATIC_ASSERT((is_assignable<int, long>::value)); 63STATIC_ASSERT((is_assignable<X>::value)); 64STATIC_ASSERT((!is_assignable<int*, int>::value)); 65STATIC_ASSERT((is_assignable<int*>::value)); 66STATIC_ASSERT((is_assignable<X, Y>::value)); 67STATIC_ASSERT((!is_assignable<X, Z>::value)); 68STATIC_ASSERT((!is_assignable<Y>::value)); 69STATIC_ASSERT((!is_assignable<const int, long>::value)); 70 71// has_plus_assign 72DEFINE_INFIX_BINARY_TRAIT(has_plus_assign, +=); 73X& operator+=(X&, Y); 74STATIC_ASSERT((has_plus_assign<int>::value)); 75STATIC_ASSERT((has_plus_assign<int, long>::value)); 76STATIC_ASSERT((has_plus_assign<X>::value)); 77STATIC_ASSERT((has_plus_assign<int*, int>::value)); 78STATIC_ASSERT((!has_plus_assign<int*>::value)); 79STATIC_ASSERT((has_plus_assign<X, Y>::value)); 80STATIC_ASSERT((!has_plus_assign<X, Z>::value)); 81STATIC_ASSERT((!has_plus_assign<Y>::value)); 82STATIC_ASSERT((!has_plus_assign<const int, long>::value)); 83 84// has_minus_assign 85DEFINE_INFIX_BINARY_TRAIT(has_minus_assign, -=); 86X& operator-=(X&, Y); 87STATIC_ASSERT((has_minus_assign<int>::value)); 88STATIC_ASSERT((has_minus_assign<int, long>::value)); 89STATIC_ASSERT((has_minus_assign<X>::value)); 90STATIC_ASSERT((has_minus_assign<int*, int>::value)); 91STATIC_ASSERT((!has_minus_assign<int*>::value)); 92STATIC_ASSERT((has_minus_assign<X, Y>::value)); 93STATIC_ASSERT((!has_minus_assign<X, Z>::value)); 94STATIC_ASSERT((!has_minus_assign<Y>::value)); 95STATIC_ASSERT((!has_minus_assign<int X::*>::value)); 96STATIC_ASSERT((!has_minus_assign<const int, long>::value)); 97 98// has_multiply_assign 99DEFINE_INFIX_BINARY_TRAIT(has_multiply_assign, *=); 100X& operator*=(X&, Y); 101STATIC_ASSERT((has_multiply_assign<int>::value)); 102STATIC_ASSERT((has_multiply_assign<int, long>::value)); 103STATIC_ASSERT((has_multiply_assign<X>::value)); 104STATIC_ASSERT((!has_multiply_assign<int*, int>::value)); 105STATIC_ASSERT((!has_multiply_assign<int*>::value)); 106STATIC_ASSERT((has_multiply_assign<X, Y>::value)); 107STATIC_ASSERT((!has_multiply_assign<X, Z>::value)); 108STATIC_ASSERT((!has_multiply_assign<Y>::value)); 109STATIC_ASSERT((!has_multiply_assign<int X::*>::value)); 110STATIC_ASSERT((!has_multiply_assign<const int, long>::value)); 111 112// has_divide_assign 113DEFINE_INFIX_BINARY_TRAIT(has_divide_assign, /=); 114X& operator/=(X&, Y); 115STATIC_ASSERT((has_divide_assign<int>::value)); 116STATIC_ASSERT((has_divide_assign<int, long>::value)); 117STATIC_ASSERT((has_divide_assign<X>::value)); 118STATIC_ASSERT((!has_divide_assign<int*, int>::value)); 119STATIC_ASSERT((!has_divide_assign<int*>::value)); 120STATIC_ASSERT((has_divide_assign<X, Y>::value)); 121STATIC_ASSERT((!has_divide_assign<X, Z>::value)); 122STATIC_ASSERT((!has_divide_assign<Y>::value)); 123STATIC_ASSERT((!has_divide_assign<int X::*>::value)); 124 125// has_remainder_assign 126DEFINE_INFIX_BINARY_TRAIT(has_remainder_assign, %=); 127X& operator%=(X&, Y); 128STATIC_ASSERT((has_remainder_assign<int>::value)); 129STATIC_ASSERT((has_remainder_assign<int, long>::value)); 130STATIC_ASSERT((!has_remainder_assign<float>::value)); 131STATIC_ASSERT((has_remainder_assign<X>::value)); 132STATIC_ASSERT((!has_remainder_assign<int*, int>::value)); 133STATIC_ASSERT((!has_remainder_assign<int*>::value)); 134STATIC_ASSERT((has_remainder_assign<X, Y>::value)); 135STATIC_ASSERT((!has_remainder_assign<X, Z>::value)); 136STATIC_ASSERT((!has_remainder_assign<Y>::value)); 137STATIC_ASSERT((!has_remainder_assign<int X::*>::value)); 138 139// has_xor_assign 140DEFINE_INFIX_BINARY_TRAIT(has_xor_assign, ^=); 141X& operator^=(X&, Y); 142STATIC_ASSERT((has_xor_assign<int>::value)); 143STATIC_ASSERT((has_xor_assign<int, long>::value)); 144STATIC_ASSERT((!has_xor_assign<float>::value)); 145STATIC_ASSERT((has_xor_assign<X>::value)); 146STATIC_ASSERT((!has_xor_assign<int*, int>::value)); 147STATIC_ASSERT((!has_xor_assign<int*>::value)); 148STATIC_ASSERT((has_xor_assign<X, Y>::value)); 149STATIC_ASSERT((!has_xor_assign<X, Z>::value)); 150STATIC_ASSERT((!has_xor_assign<Y>::value)); 151STATIC_ASSERT((!has_xor_assign<int X::*>::value)); 152 153// has_bitand_assign 154DEFINE_INFIX_BINARY_TRAIT(has_bitand_assign, &=); 155X& operator&=(X&, Y); 156STATIC_ASSERT((has_bitand_assign<int>::value)); 157STATIC_ASSERT((has_bitand_assign<int, long>::value)); 158STATIC_ASSERT((!has_bitand_assign<float>::value)); 159STATIC_ASSERT((has_bitand_assign<X>::value)); 160STATIC_ASSERT((!has_bitand_assign<int*, int>::value)); 161STATIC_ASSERT((!has_bitand_assign<int*>::value)); 162STATIC_ASSERT((has_bitand_assign<X, Y>::value)); 163STATIC_ASSERT((!has_bitand_assign<X, Z>::value)); 164STATIC_ASSERT((!has_bitand_assign<Y>::value)); 165STATIC_ASSERT((!has_bitand_assign<int X::*>::value)); 166 167// has_bitor_assign 168DEFINE_INFIX_BINARY_TRAIT(has_bitor_assign, |=); 169X& operator|=(X&, Y); 170STATIC_ASSERT((has_bitor_assign<int>::value)); 171STATIC_ASSERT((has_bitor_assign<int, long>::value)); 172STATIC_ASSERT((!has_bitor_assign<float>::value)); 173STATIC_ASSERT((has_bitor_assign<X>::value)); 174STATIC_ASSERT((!has_bitor_assign<int*, int>::value)); 175STATIC_ASSERT((!has_bitor_assign<int*>::value)); 176STATIC_ASSERT((has_bitor_assign<X, Y>::value)); 177STATIC_ASSERT((!has_bitor_assign<X, Z>::value)); 178STATIC_ASSERT((!has_bitor_assign<Y>::value)); 179STATIC_ASSERT((!has_bitor_assign<int X::*>::value)); 180 181// has_left_shift_assign 182DEFINE_INFIX_BINARY_TRAIT(has_left_shift_assign, <<=); 183X& operator<<=(X&, Y); 184STATIC_ASSERT((has_left_shift_assign<int>::value)); 185STATIC_ASSERT((has_left_shift_assign<int, long>::value)); 186STATIC_ASSERT((!has_left_shift_assign<float>::value)); 187STATIC_ASSERT((has_left_shift_assign<X>::value)); 188STATIC_ASSERT((!has_left_shift_assign<int*, int>::value)); 189STATIC_ASSERT((!has_left_shift_assign<int*>::value)); 190STATIC_ASSERT((has_left_shift_assign<X, Y>::value)); 191STATIC_ASSERT((!has_left_shift_assign<X, Z>::value)); 192STATIC_ASSERT((!has_left_shift_assign<Y>::value)); 193STATIC_ASSERT((!has_left_shift_assign<int X::*>::value)); 194 195// has_right_shift_assign 196DEFINE_INFIX_BINARY_TRAIT(has_right_shift_assign, >>=); 197X& operator>>=(X&, Y); 198STATIC_ASSERT((has_right_shift_assign<int>::value)); 199STATIC_ASSERT((has_right_shift_assign<int, long>::value)); 200STATIC_ASSERT((!has_right_shift_assign<float>::value)); 201STATIC_ASSERT((has_right_shift_assign<X>::value)); 202STATIC_ASSERT((!has_right_shift_assign<int*, int>::value)); 203STATIC_ASSERT((!has_right_shift_assign<int*>::value)); 204STATIC_ASSERT((has_right_shift_assign<X, Y>::value)); 205STATIC_ASSERT((!has_right_shift_assign<X, Z>::value)); 206STATIC_ASSERT((!has_right_shift_assign<Y>::value)); 207STATIC_ASSERT((!has_right_shift_assign<int X::*>::value)); 208