1 // { dg-do run { target c++17 } } 2 // { dg-options "-fconcepts" } 3 4 #include <cassert> 5 6 template<typename T> C()7 concept bool C() { return __is_class(T); } 8 9 template<typename T> D()10 concept bool D() { return __is_empty(T); } 11 12 struct X { } x; 13 struct Y { int n; } y; 14 15 int called = 0; 16 17 // Test constrained member definitions 18 template<typename T> 19 struct S1 { f1S120 void f1() requires C<T>() { } 21 f2S122 void f2() requires C<T>() { called = 1; } f2S123 void f2() requires not C<T>() { called = 2; } 24 f3S125 void f3() { called = 1; } f3S126 void f3() requires C<T>() { called = 2; } f3S127 void f3() requires C<T>() and D<T>() { called = 3; } 28 29 void g1() requires C<T>() and true; 30 31 void g2() requires C<T>(); 32 void g2() requires not C<T>(); 33 34 void g3(); 35 void g3() requires C<T>(); 36 void g3() requires C<T>() and D<T>(); 37 h1S138 template<C U> void h1(U u) { called = 1; } 39 template<C U> void h2(U u); 40 template<C U> void h3(U u) requires D<U>(); 41 }; 42 43 template<C T> 44 struct S2 { 45 void f(T) requires D<T>(); 46 }; 47 48 main()49int main() { 50 S1<X> sx; 51 S1<Y> sy; 52 S1<int> si; 53 54 // Defined in-class 55 sx.f1(); 56 sx.f2(); assert(called == 1); 57 sx.f3(); assert(called == 3); 58 59 sy.f1(); 60 sy.f2(); assert(called == 1); 61 sy.f3(); assert(called == 2); 62 63 si.f2(); assert(called == 2); 64 si.f3(); assert(called == 1); 65 66 // Member function template tests 67 S1<int> s1i; 68 s1i.h1(x); assert(called == 1); 69 s1i.h2(x); assert(called == 2); 70 s1i.h3(x); assert(called == 3); 71 72 // Defined out of class. 73 sx.g1(); 74 sx.g2(); assert(called == 1); 75 sx.g3(); assert(called == 3); 76 77 sy.g1(); 78 sy.g2(); assert(called == 1); 79 sy.g3(); assert(called == 2); 80 81 si.g2(); assert(called == 2); 82 si.g3(); assert(called == 1); 83 } 84 85 template<typename T> g1()86 void S1<T>::g1() requires C<T>() and true { } 87 88 template<typename T> g2()89 void S1<T>::g2() requires C<T>() { called = 1; } 90 91 template<typename T> g2()92 void S1<T>::g2() requires not C<T>() { called = 2; } 93 94 template<typename T> g3()95 void S1<T>::g3() { called = 1; } 96 97 template<typename T> g3()98 void S1<T>::g3() requires C<T>() { called = 2; } 99 100 template<typename T> g3()101 void S1<T>::g3() requires C<T>() and D<T>() { called = 3; } 102 103 template<typename T> 104 template<C U> h2(U u)105 void S1<T>::h2(U u) { called = 2; } 106 107 template<typename T> 108 template<C U> h3(U u)109 void S1<T>::h3(U u) requires D<U>() { called = 3; } 110 111 template<C T> f(T t)112 void S2<T>::f(T t) requires D<T>() { called = 4; } 113