3 // Test of the use of various binary operators with SFINAE
7 struct no_type { char data[2]; };
9 template<typename T> T create_a();
10 template<typename T> struct type { };
12 template<bool, typename T = void> struct enable_if { typedef T type; };
13 template<typename T> struct enable_if<false, T> { };
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
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), \
23 JOIN(check_,Name)(type<T>, type<U>); \
25 no_type JOIN(check_,Name)(...); \
27 template<typename T, typename U = T> \
30 static const bool value = \
31 (sizeof(JOIN(check_,Name)(type<T>(), type<U>())) == sizeof(yes_type)); \
34 template<typename T, typename U>
35 typename enable_if<(sizeof(create_a<T>()[create_a<U>()], 1) > 0),
39 template<typename T, typename U>
40 no_type check_subscript(...);
42 template<typename T, typename U>
45 static const bool value =
46 (sizeof(check_subscript<T, U>(0)) == sizeof(yes_type));
49 #ifdef __GXX_EXPERIMENTAL_CXX0X__
50 # define STATIC_ASSERT(Expr) static_assert(Expr, #Expr)
52 # define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1]
56 struct Y { int operator[](X); };
59 DEFINE_INFIX_BINARY_TRAIT(is_addable, +);
62 STATIC_ASSERT((is_addable<int>::value));
63 STATIC_ASSERT((is_addable<int, long>::value));
64 STATIC_ASSERT((is_addable<X>::value));
65 STATIC_ASSERT((is_addable<int*, int>::value));
66 STATIC_ASSERT((!is_addable<int*>::value));
67 STATIC_ASSERT((is_addable<X, Y>::value));
68 STATIC_ASSERT((!is_addable<Y>::value));
71 DEFINE_INFIX_BINARY_TRAIT(is_subtractable, -);
74 STATIC_ASSERT((is_subtractable<int>::value));
75 STATIC_ASSERT((is_subtractable<int, long>::value));
76 STATIC_ASSERT((is_subtractable<X>::value));
77 STATIC_ASSERT((is_subtractable<int*, int>::value));
78 STATIC_ASSERT((is_subtractable<int*>::value));
79 STATIC_ASSERT((is_subtractable<X, Y>::value));
80 STATIC_ASSERT((!is_subtractable<Y>::value));
81 STATIC_ASSERT((!is_subtractable<int X::*>::value));
84 DEFINE_INFIX_BINARY_TRAIT(is_multiplicable, *);
87 STATIC_ASSERT((is_multiplicable<int>::value));
88 STATIC_ASSERT((is_multiplicable<int, long>::value));
89 STATIC_ASSERT((is_multiplicable<X>::value));
90 STATIC_ASSERT((!is_multiplicable<int*, int>::value));
91 STATIC_ASSERT((!is_multiplicable<int*>::value));
92 STATIC_ASSERT((is_multiplicable<X, Y>::value));
93 STATIC_ASSERT((!is_multiplicable<Y>::value));
94 STATIC_ASSERT((!is_multiplicable<int X::*>::value));
97 DEFINE_INFIX_BINARY_TRAIT(is_divisible, /);
100 STATIC_ASSERT((is_divisible<int>::value));
101 STATIC_ASSERT((is_divisible<int, long>::value));
102 STATIC_ASSERT((is_divisible<X>::value));
103 STATIC_ASSERT((!is_divisible<int*, int>::value));
104 STATIC_ASSERT((!is_divisible<int*>::value));
105 STATIC_ASSERT((is_divisible<X, Y>::value));
106 STATIC_ASSERT((!is_divisible<Y>::value));
107 STATIC_ASSERT((!is_divisible<int X::*>::value));
110 DEFINE_INFIX_BINARY_TRAIT(has_remainder, %);
113 STATIC_ASSERT((has_remainder<int>::value));
114 STATIC_ASSERT((has_remainder<int, long>::value));
115 STATIC_ASSERT((!has_remainder<float>::value));
116 STATIC_ASSERT((has_remainder<X>::value));
117 STATIC_ASSERT((!has_remainder<int*, int>::value));
118 STATIC_ASSERT((!has_remainder<int*>::value));
119 STATIC_ASSERT((has_remainder<X, Y>::value));
120 STATIC_ASSERT((!has_remainder<Y>::value));
121 STATIC_ASSERT((!has_remainder<int X::*>::value));
124 DEFINE_INFIX_BINARY_TRAIT(has_xor, ^);
127 STATIC_ASSERT((has_xor<int>::value));
128 STATIC_ASSERT((has_xor<int, long>::value));
129 STATIC_ASSERT((!has_xor<float>::value));
130 STATIC_ASSERT((has_xor<X>::value));
131 STATIC_ASSERT((!has_xor<int*, int>::value));
132 STATIC_ASSERT((!has_xor<int*>::value));
133 STATIC_ASSERT((has_xor<X, Y>::value));
134 STATIC_ASSERT((!has_xor<Y>::value));
135 STATIC_ASSERT((!has_xor<int X::*>::value));
138 DEFINE_INFIX_BINARY_TRAIT(has_bitand, &);
141 STATIC_ASSERT((has_bitand<int>::value));
142 STATIC_ASSERT((has_bitand<int, long>::value));
143 STATIC_ASSERT((!has_bitand<float>::value));
144 STATIC_ASSERT((has_bitand<X>::value));
145 STATIC_ASSERT((!has_bitand<int*, int>::value));
146 STATIC_ASSERT((!has_bitand<int*>::value));
147 STATIC_ASSERT((has_bitand<X, Y>::value));
148 STATIC_ASSERT((!has_bitand<Y>::value));
149 STATIC_ASSERT((!has_bitand<int X::*>::value));
152 DEFINE_INFIX_BINARY_TRAIT(has_bitor, |);
155 STATIC_ASSERT((has_bitor<int>::value));
156 STATIC_ASSERT((has_bitor<int, long>::value));
157 STATIC_ASSERT((!has_bitor<float>::value));
158 STATIC_ASSERT((has_bitor<X>::value));
159 STATIC_ASSERT((!has_bitor<int*, int>::value));
160 STATIC_ASSERT((!has_bitor<int*>::value));
161 STATIC_ASSERT((has_bitor<X, Y>::value));
162 STATIC_ASSERT((!has_bitor<Y>::value));
163 STATIC_ASSERT((!has_bitor<int X::*>::value));
166 DEFINE_INFIX_BINARY_TRAIT(has_left_shift, <<);
169 STATIC_ASSERT((has_left_shift<int>::value));
170 STATIC_ASSERT((has_left_shift<int, long>::value));
171 STATIC_ASSERT((!has_left_shift<float>::value));
172 STATIC_ASSERT((has_left_shift<X>::value));
173 STATIC_ASSERT((!has_left_shift<int*, int>::value));
174 STATIC_ASSERT((!has_left_shift<int*>::value));
175 STATIC_ASSERT((has_left_shift<X, Y>::value));
176 STATIC_ASSERT((!has_left_shift<Y>::value));
177 STATIC_ASSERT((!has_left_shift<int X::*>::value));
180 DEFINE_INFIX_BINARY_TRAIT(has_right_shift, >>);
183 STATIC_ASSERT((has_right_shift<int>::value));
184 STATIC_ASSERT((has_right_shift<int, long>::value));
185 STATIC_ASSERT((!has_right_shift<float>::value));
186 STATIC_ASSERT((has_right_shift<X>::value));
187 STATIC_ASSERT((!has_right_shift<int*, int>::value));
188 STATIC_ASSERT((!has_right_shift<int*>::value));
189 STATIC_ASSERT((has_right_shift<X, Y>::value));
190 STATIC_ASSERT((!has_right_shift<Y>::value));
191 STATIC_ASSERT((!has_right_shift<int X::*>::value));
194 STATIC_ASSERT((can_subscript<int*, int>::value));
195 STATIC_ASSERT((can_subscript<int, int*>::value));
196 STATIC_ASSERT((can_subscript<int(&)[7], int>::value));
197 STATIC_ASSERT((can_subscript<int, int(&)[7]>::value));
198 STATIC_ASSERT((!can_subscript<X, Y>::value));
199 STATIC_ASSERT((can_subscript<Y, X>::value));