1// DR 339 2// 3// Test of the use of the comma operator with SFINAE 4 5// Boilerplate helpers 6typedef char yes_type; 7struct no_type { char data[2]; }; 8 9template<typename T> T create_a(); 10template<typename T> struct type { }; 11 12template<bool, typename T = void> struct enable_if { typedef T type; }; 13template<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 19template<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 24template<typename T, typename U> no_type check_comma(...); 25 26template<typename T, typename U> 27struct 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 39struct X { }; 40struct Y { }; 41struct Z { }; 42 43bool operator,(X&, Y); 44bool operator,(X, Z); 45void operator,(const Y&, const Z&); 46 47STATIC_ASSERT((has_comma<int, float>::value)); 48STATIC_ASSERT((has_comma<int, X>::value)); 49STATIC_ASSERT((has_comma<X, X>::value)); 50STATIC_ASSERT((has_comma<X, Y>::value)); 51STATIC_ASSERT((has_comma<X&, Y>::value)); 52STATIC_ASSERT((has_comma<X, Z>::value)); 53STATIC_ASSERT((!has_comma<Y, Z>::value)); 54