1 // DR 339 2 // 3 // Test of the use of various assignment 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 #define DEFINE_INFIX_BINARY_TRAIT(Name,Op) \ 20 template<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 \ 25 no_type JOIN(check_,Name)(...); \ 26 \ 27 template<typename T, typename U = T> \ 28 struct 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 40 struct Y { 41 Y& operator=(Y&); 42 }; 43 44 struct 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 }; 57 struct Z { }; 58 59 // is_assignable 60 DEFINE_INFIX_BINARY_TRAIT(is_assignable, =); 61 STATIC_ASSERT((is_assignable<int>::value)); 62 STATIC_ASSERT((is_assignable<int, long>::value)); 63 STATIC_ASSERT((is_assignable<X>::value)); 64 STATIC_ASSERT((!is_assignable<int*, int>::value)); 65 STATIC_ASSERT((is_assignable<int*>::value)); 66 STATIC_ASSERT((is_assignable<X, Y>::value)); 67 STATIC_ASSERT((!is_assignable<X, Z>::value)); 68 STATIC_ASSERT((!is_assignable<Y>::value)); 69 STATIC_ASSERT((!is_assignable<const int, long>::value)); 70 71 // has_plus_assign 72 DEFINE_INFIX_BINARY_TRAIT(has_plus_assign, +=); 73 X& operator+=(X&, Y); 74 STATIC_ASSERT((has_plus_assign<int>::value)); 75 STATIC_ASSERT((has_plus_assign<int, long>::value)); 76 STATIC_ASSERT((has_plus_assign<X>::value)); 77 STATIC_ASSERT((has_plus_assign<int*, int>::value)); 78 STATIC_ASSERT((!has_plus_assign<int*>::value)); 79 STATIC_ASSERT((has_plus_assign<X, Y>::value)); 80 STATIC_ASSERT((!has_plus_assign<X, Z>::value)); 81 STATIC_ASSERT((!has_plus_assign<Y>::value)); 82 STATIC_ASSERT((!has_plus_assign<const int, long>::value)); 83 84 // has_minus_assign 85 DEFINE_INFIX_BINARY_TRAIT(has_minus_assign, -=); 86 X& operator-=(X&, Y); 87 STATIC_ASSERT((has_minus_assign<int>::value)); 88 STATIC_ASSERT((has_minus_assign<int, long>::value)); 89 STATIC_ASSERT((has_minus_assign<X>::value)); 90 STATIC_ASSERT((has_minus_assign<int*, int>::value)); 91 STATIC_ASSERT((!has_minus_assign<int*>::value)); 92 STATIC_ASSERT((has_minus_assign<X, Y>::value)); 93 STATIC_ASSERT((!has_minus_assign<X, Z>::value)); 94 STATIC_ASSERT((!has_minus_assign<Y>::value)); 95 STATIC_ASSERT((!has_minus_assign<int X::*>::value)); 96 STATIC_ASSERT((!has_minus_assign<const int, long>::value)); 97 98 // has_multiply_assign 99 DEFINE_INFIX_BINARY_TRAIT(has_multiply_assign, *=); 100 X& operator*=(X&, Y); 101 STATIC_ASSERT((has_multiply_assign<int>::value)); 102 STATIC_ASSERT((has_multiply_assign<int, long>::value)); 103 STATIC_ASSERT((has_multiply_assign<X>::value)); 104 STATIC_ASSERT((!has_multiply_assign<int*, int>::value)); 105 STATIC_ASSERT((!has_multiply_assign<int*>::value)); 106 STATIC_ASSERT((has_multiply_assign<X, Y>::value)); 107 STATIC_ASSERT((!has_multiply_assign<X, Z>::value)); 108 STATIC_ASSERT((!has_multiply_assign<Y>::value)); 109 STATIC_ASSERT((!has_multiply_assign<int X::*>::value)); 110 STATIC_ASSERT((!has_multiply_assign<const int, long>::value)); 111 112 // has_divide_assign 113 DEFINE_INFIX_BINARY_TRAIT(has_divide_assign, /=); 114 X& operator/=(X&, Y); 115 STATIC_ASSERT((has_divide_assign<int>::value)); 116 STATIC_ASSERT((has_divide_assign<int, long>::value)); 117 STATIC_ASSERT((has_divide_assign<X>::value)); 118 STATIC_ASSERT((!has_divide_assign<int*, int>::value)); 119 STATIC_ASSERT((!has_divide_assign<int*>::value)); 120 STATIC_ASSERT((has_divide_assign<X, Y>::value)); 121 STATIC_ASSERT((!has_divide_assign<X, Z>::value)); 122 STATIC_ASSERT((!has_divide_assign<Y>::value)); 123 STATIC_ASSERT((!has_divide_assign<int X::*>::value)); 124 125 // has_remainder_assign 126 DEFINE_INFIX_BINARY_TRAIT(has_remainder_assign, %=); 127 X& operator%=(X&, Y); 128 STATIC_ASSERT((has_remainder_assign<int>::value)); 129 STATIC_ASSERT((has_remainder_assign<int, long>::value)); 130 STATIC_ASSERT((!has_remainder_assign<float>::value)); 131 STATIC_ASSERT((has_remainder_assign<X>::value)); 132 STATIC_ASSERT((!has_remainder_assign<int*, int>::value)); 133 STATIC_ASSERT((!has_remainder_assign<int*>::value)); 134 STATIC_ASSERT((has_remainder_assign<X, Y>::value)); 135 STATIC_ASSERT((!has_remainder_assign<X, Z>::value)); 136 STATIC_ASSERT((!has_remainder_assign<Y>::value)); 137 STATIC_ASSERT((!has_remainder_assign<int X::*>::value)); 138 139 // has_xor_assign 140 DEFINE_INFIX_BINARY_TRAIT(has_xor_assign, ^=); 141 X& operator^=(X&, Y); 142 STATIC_ASSERT((has_xor_assign<int>::value)); 143 STATIC_ASSERT((has_xor_assign<int, long>::value)); 144 STATIC_ASSERT((!has_xor_assign<float>::value)); 145 STATIC_ASSERT((has_xor_assign<X>::value)); 146 STATIC_ASSERT((!has_xor_assign<int*, int>::value)); 147 STATIC_ASSERT((!has_xor_assign<int*>::value)); 148 STATIC_ASSERT((has_xor_assign<X, Y>::value)); 149 STATIC_ASSERT((!has_xor_assign<X, Z>::value)); 150 STATIC_ASSERT((!has_xor_assign<Y>::value)); 151 STATIC_ASSERT((!has_xor_assign<int X::*>::value)); 152 153 // has_bitand_assign 154 DEFINE_INFIX_BINARY_TRAIT(has_bitand_assign, &=); 155 X& operator&=(X&, Y); 156 STATIC_ASSERT((has_bitand_assign<int>::value)); 157 STATIC_ASSERT((has_bitand_assign<int, long>::value)); 158 STATIC_ASSERT((!has_bitand_assign<float>::value)); 159 STATIC_ASSERT((has_bitand_assign<X>::value)); 160 STATIC_ASSERT((!has_bitand_assign<int*, int>::value)); 161 STATIC_ASSERT((!has_bitand_assign<int*>::value)); 162 STATIC_ASSERT((has_bitand_assign<X, Y>::value)); 163 STATIC_ASSERT((!has_bitand_assign<X, Z>::value)); 164 STATIC_ASSERT((!has_bitand_assign<Y>::value)); 165 STATIC_ASSERT((!has_bitand_assign<int X::*>::value)); 166 167 // has_bitor_assign 168 DEFINE_INFIX_BINARY_TRAIT(has_bitor_assign, |=); 169 X& operator|=(X&, Y); 170 STATIC_ASSERT((has_bitor_assign<int>::value)); 171 STATIC_ASSERT((has_bitor_assign<int, long>::value)); 172 STATIC_ASSERT((!has_bitor_assign<float>::value)); 173 STATIC_ASSERT((has_bitor_assign<X>::value)); 174 STATIC_ASSERT((!has_bitor_assign<int*, int>::value)); 175 STATIC_ASSERT((!has_bitor_assign<int*>::value)); 176 STATIC_ASSERT((has_bitor_assign<X, Y>::value)); 177 STATIC_ASSERT((!has_bitor_assign<X, Z>::value)); 178 STATIC_ASSERT((!has_bitor_assign<Y>::value)); 179 STATIC_ASSERT((!has_bitor_assign<int X::*>::value)); 180 181 // has_left_shift_assign 182 DEFINE_INFIX_BINARY_TRAIT(has_left_shift_assign, <<=); 183 X& operator<<=(X&, Y); 184 STATIC_ASSERT((has_left_shift_assign<int>::value)); 185 STATIC_ASSERT((has_left_shift_assign<int, long>::value)); 186 STATIC_ASSERT((!has_left_shift_assign<float>::value)); 187 STATIC_ASSERT((has_left_shift_assign<X>::value)); 188 STATIC_ASSERT((!has_left_shift_assign<int*, int>::value)); 189 STATIC_ASSERT((!has_left_shift_assign<int*>::value)); 190 STATIC_ASSERT((has_left_shift_assign<X, Y>::value)); 191 STATIC_ASSERT((!has_left_shift_assign<X, Z>::value)); 192 STATIC_ASSERT((!has_left_shift_assign<Y>::value)); 193 STATIC_ASSERT((!has_left_shift_assign<int X::*>::value)); 194 195 // has_right_shift_assign 196 DEFINE_INFIX_BINARY_TRAIT(has_right_shift_assign, >>=); 197 X& operator>>=(X&, Y); 198 STATIC_ASSERT((has_right_shift_assign<int>::value)); 199 STATIC_ASSERT((has_right_shift_assign<int, long>::value)); 200 STATIC_ASSERT((!has_right_shift_assign<float>::value)); 201 STATIC_ASSERT((has_right_shift_assign<X>::value)); 202 STATIC_ASSERT((!has_right_shift_assign<int*, int>::value)); 203 STATIC_ASSERT((!has_right_shift_assign<int*>::value)); 204 STATIC_ASSERT((has_right_shift_assign<X, Y>::value)); 205 STATIC_ASSERT((!has_right_shift_assign<X, Z>::value)); 206 STATIC_ASSERT((!has_right_shift_assign<Y>::value)); 207 STATIC_ASSERT((!has_right_shift_assign<int X::*>::value)); 208