summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/template/sfinae7.C
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/testsuite/g++.dg/template/sfinae7.C
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'gcc/testsuite/g++.dg/template/sfinae7.C')
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae7.C199
1 files changed, 199 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/template/sfinae7.C b/gcc/testsuite/g++.dg/template/sfinae7.C
new file mode 100644
index 000000000..8551eb279
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae7.C
@@ -0,0 +1,199 @@
+// DR 339
+//
+// Test of the use of various binary 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)); \
+}
+
+template<typename T, typename U>
+ typename enable_if<(sizeof(create_a<T>()[create_a<U>()], 1) > 0),
+ yes_type>::type
+ check_subscript(int);
+
+template<typename T, typename U>
+ no_type check_subscript(...);
+
+template<typename T, typename U>
+struct can_subscript
+{
+ static const bool value =
+ (sizeof(check_subscript<T, U>(0)) == 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 X { };
+struct Y { int operator[](X); };
+
+// is_addable
+DEFINE_INFIX_BINARY_TRAIT(is_addable, +);
+X operator+(X, X);
+X operator+(X, Y);
+STATIC_ASSERT((is_addable<int>::value));
+STATIC_ASSERT((is_addable<int, long>::value));
+STATIC_ASSERT((is_addable<X>::value));
+STATIC_ASSERT((is_addable<int*, int>::value));
+STATIC_ASSERT((!is_addable<int*>::value));
+STATIC_ASSERT((is_addable<X, Y>::value));
+STATIC_ASSERT((!is_addable<Y>::value));
+
+// is_subtractable
+DEFINE_INFIX_BINARY_TRAIT(is_subtractable, -);
+X operator-(X, X);
+X operator-(X, Y);
+STATIC_ASSERT((is_subtractable<int>::value));
+STATIC_ASSERT((is_subtractable<int, long>::value));
+STATIC_ASSERT((is_subtractable<X>::value));
+STATIC_ASSERT((is_subtractable<int*, int>::value));
+STATIC_ASSERT((is_subtractable<int*>::value));
+STATIC_ASSERT((is_subtractable<X, Y>::value));
+STATIC_ASSERT((!is_subtractable<Y>::value));
+STATIC_ASSERT((!is_subtractable<int X::*>::value));
+
+// is_multiplicable
+DEFINE_INFIX_BINARY_TRAIT(is_multiplicable, *);
+X operator*(X, X);
+X operator*(X, Y);
+STATIC_ASSERT((is_multiplicable<int>::value));
+STATIC_ASSERT((is_multiplicable<int, long>::value));
+STATIC_ASSERT((is_multiplicable<X>::value));
+STATIC_ASSERT((!is_multiplicable<int*, int>::value));
+STATIC_ASSERT((!is_multiplicable<int*>::value));
+STATIC_ASSERT((is_multiplicable<X, Y>::value));
+STATIC_ASSERT((!is_multiplicable<Y>::value));
+STATIC_ASSERT((!is_multiplicable<int X::*>::value));
+
+// is_divisible
+DEFINE_INFIX_BINARY_TRAIT(is_divisible, /);
+X operator/(X, X);
+X operator/(X, Y);
+STATIC_ASSERT((is_divisible<int>::value));
+STATIC_ASSERT((is_divisible<int, long>::value));
+STATIC_ASSERT((is_divisible<X>::value));
+STATIC_ASSERT((!is_divisible<int*, int>::value));
+STATIC_ASSERT((!is_divisible<int*>::value));
+STATIC_ASSERT((is_divisible<X, Y>::value));
+STATIC_ASSERT((!is_divisible<Y>::value));
+STATIC_ASSERT((!is_divisible<int X::*>::value));
+
+// has_remainder
+DEFINE_INFIX_BINARY_TRAIT(has_remainder, %);
+X operator%(X, X);
+X operator%(X, Y);
+STATIC_ASSERT((has_remainder<int>::value));
+STATIC_ASSERT((has_remainder<int, long>::value));
+STATIC_ASSERT((!has_remainder<float>::value));
+STATIC_ASSERT((has_remainder<X>::value));
+STATIC_ASSERT((!has_remainder<int*, int>::value));
+STATIC_ASSERT((!has_remainder<int*>::value));
+STATIC_ASSERT((has_remainder<X, Y>::value));
+STATIC_ASSERT((!has_remainder<Y>::value));
+STATIC_ASSERT((!has_remainder<int X::*>::value));
+
+// has_xor
+DEFINE_INFIX_BINARY_TRAIT(has_xor, ^);
+X operator^(X, X);
+X operator^(X, Y);
+STATIC_ASSERT((has_xor<int>::value));
+STATIC_ASSERT((has_xor<int, long>::value));
+STATIC_ASSERT((!has_xor<float>::value));
+STATIC_ASSERT((has_xor<X>::value));
+STATIC_ASSERT((!has_xor<int*, int>::value));
+STATIC_ASSERT((!has_xor<int*>::value));
+STATIC_ASSERT((has_xor<X, Y>::value));
+STATIC_ASSERT((!has_xor<Y>::value));
+STATIC_ASSERT((!has_xor<int X::*>::value));
+
+// has_bitand
+DEFINE_INFIX_BINARY_TRAIT(has_bitand, &);
+X operator&(X, X);
+X operator&(X, Y);
+STATIC_ASSERT((has_bitand<int>::value));
+STATIC_ASSERT((has_bitand<int, long>::value));
+STATIC_ASSERT((!has_bitand<float>::value));
+STATIC_ASSERT((has_bitand<X>::value));
+STATIC_ASSERT((!has_bitand<int*, int>::value));
+STATIC_ASSERT((!has_bitand<int*>::value));
+STATIC_ASSERT((has_bitand<X, Y>::value));
+STATIC_ASSERT((!has_bitand<Y>::value));
+STATIC_ASSERT((!has_bitand<int X::*>::value));
+
+// has_bitor
+DEFINE_INFIX_BINARY_TRAIT(has_bitor, |);
+X operator|(X, X);
+X operator|(X, Y);
+STATIC_ASSERT((has_bitor<int>::value));
+STATIC_ASSERT((has_bitor<int, long>::value));
+STATIC_ASSERT((!has_bitor<float>::value));
+STATIC_ASSERT((has_bitor<X>::value));
+STATIC_ASSERT((!has_bitor<int*, int>::value));
+STATIC_ASSERT((!has_bitor<int*>::value));
+STATIC_ASSERT((has_bitor<X, Y>::value));
+STATIC_ASSERT((!has_bitor<Y>::value));
+STATIC_ASSERT((!has_bitor<int X::*>::value));
+
+// has_left_shift
+DEFINE_INFIX_BINARY_TRAIT(has_left_shift, <<);
+X operator<<(X, X);
+X operator<<(X, Y);
+STATIC_ASSERT((has_left_shift<int>::value));
+STATIC_ASSERT((has_left_shift<int, long>::value));
+STATIC_ASSERT((!has_left_shift<float>::value));
+STATIC_ASSERT((has_left_shift<X>::value));
+STATIC_ASSERT((!has_left_shift<int*, int>::value));
+STATIC_ASSERT((!has_left_shift<int*>::value));
+STATIC_ASSERT((has_left_shift<X, Y>::value));
+STATIC_ASSERT((!has_left_shift<Y>::value));
+STATIC_ASSERT((!has_left_shift<int X::*>::value));
+
+// has_right_shift
+DEFINE_INFIX_BINARY_TRAIT(has_right_shift, >>);
+X operator>>(X, X);
+X operator>>(X, Y);
+STATIC_ASSERT((has_right_shift<int>::value));
+STATIC_ASSERT((has_right_shift<int, long>::value));
+STATIC_ASSERT((!has_right_shift<float>::value));
+STATIC_ASSERT((has_right_shift<X>::value));
+STATIC_ASSERT((!has_right_shift<int*, int>::value));
+STATIC_ASSERT((!has_right_shift<int*>::value));
+STATIC_ASSERT((has_right_shift<X, Y>::value));
+STATIC_ASSERT((!has_right_shift<Y>::value));
+STATIC_ASSERT((!has_right_shift<int X::*>::value));
+
+// can_subscript
+STATIC_ASSERT((can_subscript<int*, int>::value));
+STATIC_ASSERT((can_subscript<int, int*>::value));
+STATIC_ASSERT((can_subscript<int(&)[7], int>::value));
+STATIC_ASSERT((can_subscript<int, int(&)[7]>::value));
+STATIC_ASSERT((!can_subscript<X, Y>::value));
+STATIC_ASSERT((can_subscript<Y, X>::value));