summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/template/sfinae9.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/template/sfinae9.C')
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae9.C207
1 files changed, 207 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/template/sfinae9.C b/gcc/testsuite/g++.dg/template/sfinae9.C
new file mode 100644
index 000000000..4e27ff61b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae9.C
@@ -0,0 +1,207 @@
+// DR 339
+//
+// Test of the use of various assignment operators with SFINAE
+
+// Boilerplate helpers
+typedef char yes_type;
+struct no_type { char data[2]; };
+
+template<typename T> T create_a();
+template<typename T> struct type { };
+
+template<bool, typename T = void> struct enable_if { typedef T type; };
+template<typename T> struct enable_if<false, T> { };
+
+#define JOIN( X, Y ) DO_JOIN( X, Y )
+#define DO_JOIN( X, Y ) DO_JOIN2(X,Y)
+#define DO_JOIN2( X, Y ) X##Y
+
+#define DEFINE_INFIX_BINARY_TRAIT(Name,Op) \
+template<typename T, typename U> \
+ typename enable_if<(sizeof(create_a<T>() Op create_a<U>(), 1) > 0), \
+ yes_type>::type \
+ JOIN(check_,Name)(type<T>, type<U>); \
+ \
+no_type JOIN(check_,Name)(...); \
+ \
+template<typename T, typename U = T> \
+struct Name \
+{ \
+ static const bool value = \
+ (sizeof(JOIN(check_,Name)(type<T&>(), type<U>())) == sizeof(yes_type)); \
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr)
+#else
+# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1]
+#endif
+
+struct Y {
+ Y& operator=(Y&);
+};
+
+struct X {
+ X& operator=(Y);
+ X& operator+=(X);
+ X& operator-=(X);
+ X& operator*=(X);
+ X& operator/=(X);
+ X& operator%=(X);
+ X& operator^=(X);
+ X& operator&=(X);
+ X& operator|=(X);
+ X& operator<<=(X);
+ X& operator>>=(X);
+};
+struct Z { };
+
+// is_assignable
+DEFINE_INFIX_BINARY_TRAIT(is_assignable, =);
+STATIC_ASSERT((is_assignable<int>::value));
+STATIC_ASSERT((is_assignable<int, long>::value));
+STATIC_ASSERT((is_assignable<X>::value));
+STATIC_ASSERT((!is_assignable<int*, int>::value));
+STATIC_ASSERT((is_assignable<int*>::value));
+STATIC_ASSERT((is_assignable<X, Y>::value));
+STATIC_ASSERT((!is_assignable<X, Z>::value));
+STATIC_ASSERT((!is_assignable<Y>::value));
+STATIC_ASSERT((!is_assignable<const int, long>::value));
+
+// has_plus_assign
+DEFINE_INFIX_BINARY_TRAIT(has_plus_assign, +=);
+X& operator+=(X&, Y);
+STATIC_ASSERT((has_plus_assign<int>::value));
+STATIC_ASSERT((has_plus_assign<int, long>::value));
+STATIC_ASSERT((has_plus_assign<X>::value));
+STATIC_ASSERT((has_plus_assign<int*, int>::value));
+STATIC_ASSERT((!has_plus_assign<int*>::value));
+STATIC_ASSERT((has_plus_assign<X, Y>::value));
+STATIC_ASSERT((!has_plus_assign<X, Z>::value));
+STATIC_ASSERT((!has_plus_assign<Y>::value));
+STATIC_ASSERT((!has_plus_assign<const int, long>::value));
+
+// has_minus_assign
+DEFINE_INFIX_BINARY_TRAIT(has_minus_assign, -=);
+X& operator-=(X&, Y);
+STATIC_ASSERT((has_minus_assign<int>::value));
+STATIC_ASSERT((has_minus_assign<int, long>::value));
+STATIC_ASSERT((has_minus_assign<X>::value));
+STATIC_ASSERT((has_minus_assign<int*, int>::value));
+STATIC_ASSERT((!has_minus_assign<int*>::value));
+STATIC_ASSERT((has_minus_assign<X, Y>::value));
+STATIC_ASSERT((!has_minus_assign<X, Z>::value));
+STATIC_ASSERT((!has_minus_assign<Y>::value));
+STATIC_ASSERT((!has_minus_assign<int X::*>::value));
+STATIC_ASSERT((!has_minus_assign<const int, long>::value));
+
+// has_multiply_assign
+DEFINE_INFIX_BINARY_TRAIT(has_multiply_assign, *=);
+X& operator*=(X&, Y);
+STATIC_ASSERT((has_multiply_assign<int>::value));
+STATIC_ASSERT((has_multiply_assign<int, long>::value));
+STATIC_ASSERT((has_multiply_assign<X>::value));
+STATIC_ASSERT((!has_multiply_assign<int*, int>::value));
+STATIC_ASSERT((!has_multiply_assign<int*>::value));
+STATIC_ASSERT((has_multiply_assign<X, Y>::value));
+STATIC_ASSERT((!has_multiply_assign<X, Z>::value));
+STATIC_ASSERT((!has_multiply_assign<Y>::value));
+STATIC_ASSERT((!has_multiply_assign<int X::*>::value));
+STATIC_ASSERT((!has_multiply_assign<const int, long>::value));
+
+// has_divide_assign
+DEFINE_INFIX_BINARY_TRAIT(has_divide_assign, /=);
+X& operator/=(X&, Y);
+STATIC_ASSERT((has_divide_assign<int>::value));
+STATIC_ASSERT((has_divide_assign<int, long>::value));
+STATIC_ASSERT((has_divide_assign<X>::value));
+STATIC_ASSERT((!has_divide_assign<int*, int>::value));
+STATIC_ASSERT((!has_divide_assign<int*>::value));
+STATIC_ASSERT((has_divide_assign<X, Y>::value));
+STATIC_ASSERT((!has_divide_assign<X, Z>::value));
+STATIC_ASSERT((!has_divide_assign<Y>::value));
+STATIC_ASSERT((!has_divide_assign<int X::*>::value));
+
+// has_remainder_assign
+DEFINE_INFIX_BINARY_TRAIT(has_remainder_assign, %=);
+X& operator%=(X&, Y);
+STATIC_ASSERT((has_remainder_assign<int>::value));
+STATIC_ASSERT((has_remainder_assign<int, long>::value));
+STATIC_ASSERT((!has_remainder_assign<float>::value));
+STATIC_ASSERT((has_remainder_assign<X>::value));
+STATIC_ASSERT((!has_remainder_assign<int*, int>::value));
+STATIC_ASSERT((!has_remainder_assign<int*>::value));
+STATIC_ASSERT((has_remainder_assign<X, Y>::value));
+STATIC_ASSERT((!has_remainder_assign<X, Z>::value));
+STATIC_ASSERT((!has_remainder_assign<Y>::value));
+STATIC_ASSERT((!has_remainder_assign<int X::*>::value));
+
+// has_xor_assign
+DEFINE_INFIX_BINARY_TRAIT(has_xor_assign, ^=);
+X& operator^=(X&, Y);
+STATIC_ASSERT((has_xor_assign<int>::value));
+STATIC_ASSERT((has_xor_assign<int, long>::value));
+STATIC_ASSERT((!has_xor_assign<float>::value));
+STATIC_ASSERT((has_xor_assign<X>::value));
+STATIC_ASSERT((!has_xor_assign<int*, int>::value));
+STATIC_ASSERT((!has_xor_assign<int*>::value));
+STATIC_ASSERT((has_xor_assign<X, Y>::value));
+STATIC_ASSERT((!has_xor_assign<X, Z>::value));
+STATIC_ASSERT((!has_xor_assign<Y>::value));
+STATIC_ASSERT((!has_xor_assign<int X::*>::value));
+
+// has_bitand_assign
+DEFINE_INFIX_BINARY_TRAIT(has_bitand_assign, &=);
+X& operator&=(X&, Y);
+STATIC_ASSERT((has_bitand_assign<int>::value));
+STATIC_ASSERT((has_bitand_assign<int, long>::value));
+STATIC_ASSERT((!has_bitand_assign<float>::value));
+STATIC_ASSERT((has_bitand_assign<X>::value));
+STATIC_ASSERT((!has_bitand_assign<int*, int>::value));
+STATIC_ASSERT((!has_bitand_assign<int*>::value));
+STATIC_ASSERT((has_bitand_assign<X, Y>::value));
+STATIC_ASSERT((!has_bitand_assign<X, Z>::value));
+STATIC_ASSERT((!has_bitand_assign<Y>::value));
+STATIC_ASSERT((!has_bitand_assign<int X::*>::value));
+
+// has_bitor_assign
+DEFINE_INFIX_BINARY_TRAIT(has_bitor_assign, |=);
+X& operator|=(X&, Y);
+STATIC_ASSERT((has_bitor_assign<int>::value));
+STATIC_ASSERT((has_bitor_assign<int, long>::value));
+STATIC_ASSERT((!has_bitor_assign<float>::value));
+STATIC_ASSERT((has_bitor_assign<X>::value));
+STATIC_ASSERT((!has_bitor_assign<int*, int>::value));
+STATIC_ASSERT((!has_bitor_assign<int*>::value));
+STATIC_ASSERT((has_bitor_assign<X, Y>::value));
+STATIC_ASSERT((!has_bitor_assign<X, Z>::value));
+STATIC_ASSERT((!has_bitor_assign<Y>::value));
+STATIC_ASSERT((!has_bitor_assign<int X::*>::value));
+
+// has_left_shift_assign
+DEFINE_INFIX_BINARY_TRAIT(has_left_shift_assign, <<=);
+X& operator<<=(X&, Y);
+STATIC_ASSERT((has_left_shift_assign<int>::value));
+STATIC_ASSERT((has_left_shift_assign<int, long>::value));
+STATIC_ASSERT((!has_left_shift_assign<float>::value));
+STATIC_ASSERT((has_left_shift_assign<X>::value));
+STATIC_ASSERT((!has_left_shift_assign<int*, int>::value));
+STATIC_ASSERT((!has_left_shift_assign<int*>::value));
+STATIC_ASSERT((has_left_shift_assign<X, Y>::value));
+STATIC_ASSERT((!has_left_shift_assign<X, Z>::value));
+STATIC_ASSERT((!has_left_shift_assign<Y>::value));
+STATIC_ASSERT((!has_left_shift_assign<int X::*>::value));
+
+// has_right_shift_assign
+DEFINE_INFIX_BINARY_TRAIT(has_right_shift_assign, >>=);
+X& operator>>=(X&, Y);
+STATIC_ASSERT((has_right_shift_assign<int>::value));
+STATIC_ASSERT((has_right_shift_assign<int, long>::value));
+STATIC_ASSERT((!has_right_shift_assign<float>::value));
+STATIC_ASSERT((has_right_shift_assign<X>::value));
+STATIC_ASSERT((!has_right_shift_assign<int*, int>::value));
+STATIC_ASSERT((!has_right_shift_assign<int*>::value));
+STATIC_ASSERT((has_right_shift_assign<X, Y>::value));
+STATIC_ASSERT((!has_right_shift_assign<X, Z>::value));
+STATIC_ASSERT((!has_right_shift_assign<Y>::value));
+STATIC_ASSERT((!has_right_shift_assign<int X::*>::value));