1 // DR 339 2 // 3 // Test of the use of the comma operator 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 template<typename T, typename U> 20 typename enable_if<(sizeof(create_a<T>(), create_a<U>()) > 0), 21 yes_type>::type 22 check_comma(int); 23 24 template<typename T, typename U> no_type check_comma(...); 25 26 template<typename T, typename U> 27 struct has_comma 28 { 29 static const bool value = 30 (sizeof(check_comma<T, U>(0)) == sizeof(yes_type)); 31 }; 32 33 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 34 # define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) 35 #else 36 # define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] 37 #endif 38 39 struct X { }; 40 struct Y { }; 41 struct Z { }; 42 43 bool operator,(X&, Y); 44 bool operator,(X, Z); 45 void operator,(const Y&, const Z&); 46 47 STATIC_ASSERT((has_comma<int, float>::value)); 48 STATIC_ASSERT((has_comma<int, X>::value)); 49 STATIC_ASSERT((has_comma<X, X>::value)); 50 STATIC_ASSERT((has_comma<X, Y>::value)); 51 STATIC_ASSERT((has_comma<X&, Y>::value)); 52 STATIC_ASSERT((has_comma<X, Z>::value)); 53 STATIC_ASSERT((!has_comma<Y, Z>::value)); 54