summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/template/sfinae8.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/template/sfinae8.C')
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae8.C182
1 files changed, 182 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/template/sfinae8.C b/gcc/testsuite/g++.dg/template/sfinae8.C
new file mode 100644
index 000000000..5ac09c6b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae8.C
@@ -0,0 +1,182 @@
+// DR 339
+//
+// Test of the use of various boolean 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
+
+bool accepts_bool(bool);
+
+#define DEFINE_BINARY_PREDICATE_TRAIT(Name,Op) \
+template<typename T, typename U> \
+ typename enable_if<sizeof(accepts_bool(create_a<T>() Op create_a<U>())), \
+ 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 X { };
+struct Y { };
+
+struct convertible_to_bool {
+ operator int convertible_to_bool::* ();
+};
+
+struct not_convertible_to_bool { };
+
+// is_less_than_comparable
+DEFINE_BINARY_PREDICATE_TRAIT(is_less_than_comparable,<);
+bool operator<(X, X);
+convertible_to_bool operator<(X, Y);
+not_convertible_to_bool operator<(Y, X);
+
+STATIC_ASSERT((is_less_than_comparable<int>::value));
+STATIC_ASSERT((is_less_than_comparable<int, long>::value));
+STATIC_ASSERT((is_less_than_comparable<int*>::value));
+STATIC_ASSERT((is_less_than_comparable<X>::value));
+STATIC_ASSERT((is_less_than_comparable<X, Y>::value));
+STATIC_ASSERT((!is_less_than_comparable<Y, X>::value));
+STATIC_ASSERT((!is_less_than_comparable<Y>::value));
+
+// is_less_equal_comparable
+DEFINE_BINARY_PREDICATE_TRAIT(is_less_equal_comparable,<=);
+bool operator<=(X, X);
+convertible_to_bool operator<=(X, Y);
+not_convertible_to_bool operator<=(Y, X);
+
+STATIC_ASSERT((is_less_equal_comparable<int>::value));
+STATIC_ASSERT((is_less_equal_comparable<int, long>::value));
+STATIC_ASSERT((is_less_equal_comparable<int*>::value));
+STATIC_ASSERT((is_less_equal_comparable<X>::value));
+STATIC_ASSERT((is_less_equal_comparable<X, Y>::value));
+STATIC_ASSERT((!is_less_equal_comparable<Y, X>::value));
+STATIC_ASSERT((!is_less_equal_comparable<Y>::value));
+
+// is_greater_than_comparable
+DEFINE_BINARY_PREDICATE_TRAIT(is_greater_than_comparable,>);
+bool operator>(X, X);
+convertible_to_bool operator>(X, Y);
+not_convertible_to_bool operator>(Y, X);
+
+STATIC_ASSERT((is_greater_than_comparable<int>::value));
+STATIC_ASSERT((is_greater_than_comparable<int, long>::value));
+STATIC_ASSERT((is_greater_than_comparable<int*>::value));
+STATIC_ASSERT((is_greater_than_comparable<X>::value));
+STATIC_ASSERT((is_greater_than_comparable<X, Y>::value));
+STATIC_ASSERT((!is_greater_than_comparable<Y, X>::value));
+STATIC_ASSERT((!is_greater_than_comparable<Y>::value));
+
+// is_greater_equal_comparable
+DEFINE_BINARY_PREDICATE_TRAIT(is_greater_equal_comparable,>=);
+bool operator>=(X, X);
+convertible_to_bool operator>=(X, Y);
+not_convertible_to_bool operator>=(Y, X);
+
+STATIC_ASSERT((is_greater_equal_comparable<int>::value));
+STATIC_ASSERT((is_greater_equal_comparable<int, long>::value));
+STATIC_ASSERT((is_greater_equal_comparable<int*>::value));
+STATIC_ASSERT((is_greater_equal_comparable<X>::value));
+STATIC_ASSERT((is_greater_equal_comparable<X, Y>::value));
+STATIC_ASSERT((!is_greater_equal_comparable<Y, X>::value));
+STATIC_ASSERT((!is_greater_equal_comparable<Y>::value));
+
+// is_equality_comparable
+struct Z : X { };
+DEFINE_BINARY_PREDICATE_TRAIT(is_equality_comparable,==);
+bool operator==(X, X);
+convertible_to_bool operator==(X, Y);
+not_convertible_to_bool operator==(Y, X);
+
+STATIC_ASSERT((is_equality_comparable<int>::value));
+STATIC_ASSERT((is_equality_comparable<int, long>::value));
+STATIC_ASSERT((is_equality_comparable<int*>::value));
+STATIC_ASSERT((is_equality_comparable<X>::value));
+STATIC_ASSERT((is_equality_comparable<X, Y>::value));
+STATIC_ASSERT((!is_equality_comparable<Y, X>::value));
+STATIC_ASSERT((!is_equality_comparable<Y>::value));
+STATIC_ASSERT((is_equality_comparable<int X::*>::value));
+STATIC_ASSERT((!is_equality_comparable<int X::*, int Y::*>::value));
+STATIC_ASSERT((!is_equality_comparable<int*, float*>::value));
+STATIC_ASSERT((is_equality_comparable<X*, Z*>::value));
+STATIC_ASSERT((!is_equality_comparable<X*, Y*>::value));
+
+// is_not_equal_comparable
+DEFINE_BINARY_PREDICATE_TRAIT(is_not_equal_comparable,!=);
+bool operator!=(X, X);
+convertible_to_bool operator!=(X, Y);
+not_convertible_to_bool operator!=(Y, X);
+
+STATIC_ASSERT((is_not_equal_comparable<int>::value));
+STATIC_ASSERT((is_not_equal_comparable<int, long>::value));
+STATIC_ASSERT((is_not_equal_comparable<int*>::value));
+STATIC_ASSERT((is_not_equal_comparable<X>::value));
+STATIC_ASSERT((is_not_equal_comparable<X, Y>::value));
+STATIC_ASSERT((!is_not_equal_comparable<Y, X>::value));
+STATIC_ASSERT((!is_not_equal_comparable<Y>::value));
+STATIC_ASSERT((is_not_equal_comparable<int X::*>::value));
+STATIC_ASSERT((!is_not_equal_comparable<int X::*, int Y::*>::value));
+STATIC_ASSERT((!is_not_equal_comparable<int*, float*>::value));
+STATIC_ASSERT((is_not_equal_comparable<X*, Z*>::value));
+STATIC_ASSERT((!is_not_equal_comparable<X*, Y*>::value));
+
+// has_logical_and
+DEFINE_BINARY_PREDICATE_TRAIT(has_logical_and,&&);
+bool operator&&(X, X);
+convertible_to_bool operator&&(X, Y);
+not_convertible_to_bool operator&&(Y, X);
+
+STATIC_ASSERT((has_logical_and<int>::value));
+STATIC_ASSERT((has_logical_and<int, long>::value));
+STATIC_ASSERT((has_logical_and<int*>::value));
+STATIC_ASSERT((has_logical_and<X>::value));
+STATIC_ASSERT((has_logical_and<X, Y>::value));
+STATIC_ASSERT((!has_logical_and<Y, X>::value));
+STATIC_ASSERT((!has_logical_and<Y>::value));
+STATIC_ASSERT((has_logical_and<int X::*>::value));
+STATIC_ASSERT((has_logical_and<int X::*, int Y::*>::value));
+STATIC_ASSERT((has_logical_and<int*, float*>::value));
+STATIC_ASSERT((has_logical_and<X*, Z*>::value));
+STATIC_ASSERT((has_logical_and<X*, Y*>::value));
+
+// has_logical_or
+DEFINE_BINARY_PREDICATE_TRAIT(has_logical_or,||);
+bool operator||(X, X);
+convertible_to_bool operator||(X, Y);
+not_convertible_to_bool operator||(Y, X);
+
+STATIC_ASSERT((has_logical_or<int>::value));
+STATIC_ASSERT((has_logical_or<int, long>::value));
+STATIC_ASSERT((has_logical_or<int*>::value));
+STATIC_ASSERT((has_logical_or<X>::value));
+STATIC_ASSERT((has_logical_or<X, Y>::value));
+STATIC_ASSERT((!has_logical_or<Y, X>::value));
+STATIC_ASSERT((!has_logical_or<Y>::value));
+STATIC_ASSERT((has_logical_or<int X::*>::value));
+STATIC_ASSERT((has_logical_or<int X::*, int Y::*>::value));
+STATIC_ASSERT((has_logical_or<int*, float*>::value));
+STATIC_ASSERT((has_logical_or<X*, Z*>::value));
+STATIC_ASSERT((has_logical_or<X*, Y*>::value));