OSDN Git Service

2008-03-25 Douglas Gregor <doug.gregor@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / g++.dg / template / sfinae7.C
1 // DR 339
2 //
3 // Test of the use of various 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 #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 template<typename T, typename U>
35   typename enable_if<(sizeof(create_a<T>()[create_a<U>()], 1) > 0),
36                      yes_type>::type
37   check_subscript(int);
38
39 template<typename T, typename U>
40   no_type check_subscript(...);
41
42 template<typename T, typename U>
43 struct can_subscript
44 {
45   static const bool value = 
46     (sizeof(check_subscript<T, U>(0)) == sizeof(yes_type));
47 };
48
49 #ifdef __GXX_EXPERIMENTAL_CXX0X__
50 #  define STATIC_ASSERT(Expr) static_assert(Expr, #Expr)
51 #else
52 #  define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1]
53 #endif
54
55 struct X { };
56 struct Y { int operator[](X); };
57
58 // is_addable
59 DEFINE_INFIX_BINARY_TRAIT(is_addable, +);
60 X operator+(X, X);
61 X operator+(X, Y);
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));
69
70 // is_subtractable
71 DEFINE_INFIX_BINARY_TRAIT(is_subtractable, -);
72 X operator-(X, X);
73 X operator-(X, Y);
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));
82
83 // is_multiplicable
84 DEFINE_INFIX_BINARY_TRAIT(is_multiplicable, *);
85 X operator*(X, X);
86 X operator*(X, Y);
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));
95
96 // is_divisible
97 DEFINE_INFIX_BINARY_TRAIT(is_divisible, /);
98 X operator/(X, X);
99 X operator/(X, Y);
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));
108
109 // has_remainder
110 DEFINE_INFIX_BINARY_TRAIT(has_remainder, %);
111 X operator%(X, X);
112 X operator%(X, Y);
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));
122
123 // has_xor
124 DEFINE_INFIX_BINARY_TRAIT(has_xor, ^);
125 X operator^(X, X);
126 X operator^(X, Y);
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));
136
137 // has_bitand
138 DEFINE_INFIX_BINARY_TRAIT(has_bitand, &);
139 X operator&(X, X);
140 X operator&(X, Y);
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));
150
151 // has_bitor
152 DEFINE_INFIX_BINARY_TRAIT(has_bitor, |);
153 X operator|(X, X);
154 X operator|(X, Y);
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));
164
165 // has_left_shift
166 DEFINE_INFIX_BINARY_TRAIT(has_left_shift, <<);
167 X operator<<(X, X);
168 X operator<<(X, Y);
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));
178
179 // has_right_shift
180 DEFINE_INFIX_BINARY_TRAIT(has_right_shift, >>);
181 X operator>>(X, X);
182 X operator>>(X, Y);
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));
192
193 // can_subscript
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));