2014-01-30 Alangi Derick <alangiderick@gmail.com>
[official-gcc.git] / gcc / testsuite / g++.dg / template / sfinae9.C
blob4e27ff61bd5eb490cd9ce48f1b196bce4ac5d462
1 // DR 339
2 //
3 // Test of the use of various assignment operators with SFINAE
5 // Boilerplate helpers
6 typedef char yes_type;
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),   \
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)); \
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
40 struct Y { 
41   Y& operator=(Y&);
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);
57 struct Z { };
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));