1 // PR c++/87748 2 // { dg-do compile { target c++11 } } 3 4 template <class T> T&& declval(); 5 template <bool B, class T> struct enable_if; 6 template <class T> struct enable_if <true, T> { typedef T type; }; 7 struct true_type { static const bool value = true; }; 8 struct false_type { static const bool value = false; }; 9 10 struct string 11 { 12 string (const char *p); 13 }; 14 15 /// Template to map all type arguments to void, useful for SFINAE, see also WG21 N3911. 16 template<class...> using void_t = void; 17 18 /// REQUIRES<value> - Simplified version of enable_if<> to use SFINAE in function templates. 19 template<bool value> using REQUIRES = typename ::enable_if<value, bool>::type; 20 21 /// DerivesString<T> - Check if @a T is of type 'string'. 22 template<class T> struct DerivesString 23 { 24 static const int value = __is_same_as (T, string); 25 }; 26 27 /// Has__aida_visit__<T,Visitor> - Check if @a T provides a member template __aida_visit__<>(Visitor). 28 template<class, class, class = void> struct Has__aida_visit__ : false_type {}; 29 template<class T, class V> 30 struct Has__aida_visit__<T, V, void_t< decltype (declval<T>().template __aida_visit__<V> (*(V*) 0)) >> : true_type {}; 31 32 struct Foo { 33 template<class V> void __accept__ (V*); 34 }; 35 36 /// Base template for Visitor classes, dispatches operator() to visit_<type>() methods. 37 template<class DerivedVisitor> 38 class VisitorDispatcher { 39 DerivedVisitor* derived () { return static_cast<DerivedVisitor*> (this); } 40 protected: 41 typedef const char* Name; ///< Member name argument type for visit() methods. 42 public: 43 44 // dispatch for calls like: visitor (field, "field"); 45 46 template<class A, 47 REQUIRES< (!Has__aida_visit__<A, DerivedVisitor>::value) > = true> 48 void operator() (A &a, Name n) 49 { return derived()->visit_string (a, n); } 50 }; 51 52 class PspecVisitor : public VisitorDispatcher<PspecVisitor> { 53 public: 54 void visit_string (::string &a, Name name); 55 }; 56 57 int 58 main (int argc, char *argv[]) 59 { 60 #ifdef WITHASSERT // define this to fix g++-8.1.1 61 static_assert (Has__aida_visit__<string, PspecVisitor>::value == false, ""); 62 #endif 63 PspecVisitor v; 64 string str ("A string"); 65 v (str, "some_string"); 66 static_assert (Has__aida_visit__<string, PspecVisitor>::value == false, ""); 67 return 0; 68 } 69 // g++ -std=gnu++14 -Wall -O2 aidavisit.cc && ./a.out 70