[C++ PATCH] Deprecate -ffriend-injection
[official-gcc.git] / gcc / testsuite / g++.dg / concepts / generic-fn.C
blob7a48e7640d00ba49f77f6f56e8ec6a09c521dc5f
1 // { dg-do run }
2 // { dg-options "-std=c++17 -fconcepts" }
4 #include <cassert>
5 #include <type_traits>
7 template<typename T>
8   concept bool C() { return __is_class(T); }
10 template<typename T>
11   concept bool Type() { return true; }
13 struct S { };
15 int called;
17 // Basic terse notation
18 void f(auto x) { called = 1; }
19 void g(C x) { called = 2; }
21 // Overloading generic functions
22 void h(auto x) { called = 1; }
23 void h(C x) { called = 2; }
25 void p(auto x);
26 void p(C x);
28 struct S1 {
29   void f1(auto x) { called = 1; }
30   void f2(C x) { called = 2; }
32   void f3(auto x) { called = 1; }
33   void f3(C x) { called = 2; }
36 template<C T>
37   struct S2 {
38     void f1(auto x) { called = 1; }
39     void f2(C x) { called = 2; }
41     void f3(auto x) { called = 1; }
42     void f3(C x) { called = 2; }
44     void h1(auto x);
45     void h2(C x);
47     void h3(auto x);
48     void h3(C x);
50     template<C U>
51       void g1(T t, U u) { called = 1; }
53     template<C U>
54       void g2(T t, U u);
55   };
58 void ptr(C*) { called = 1; }
59 void ptr(const C*) { called = 2; }
61 void ref(C&) { called = 1; }
62 void ref(const C&) { called = 2; }
64 void
65 fwd_lvalue_ref(Type&& x) {
66   using T = decltype(x);
67   static_assert(std::is_lvalue_reference<T>::value, "not an lvlaue reference");
70 void
71 fwd_const_lvalue_ref(Type&& x) {
72   using T = decltype(x);
73   static_assert(std::is_lvalue_reference<T>::value, "not an lvalue reference");
74   using U = typename std::remove_reference<T>::type;
75   static_assert(std::is_const<U>::value, "not const-qualified");
78 void fwd_rvalue_ref(Type&& x) {
79   using T = decltype(x);
80   static_assert(std::is_rvalue_reference<T>::value, "not an rvalue reference");
83 // Make sure we can use nested names speicifers for concept names.
84 namespace N {
85   template<typename T>
86     concept bool C() { return true; }
87 } // namesspace N
89 void foo(N::C x) { }
91 int main() {
92   S s;
93   const S cs;
95   f(0); assert(called == 1);
96   g(s); assert(called == 2);
98   h(0); assert(called == 1);
99   h(s); assert(called == 2);
101   S1 s1;
102   s1.f1(0); assert(called == 1);
103   s1.f2(s); assert(called == 2);
105   s1.f3(0); assert(called == 1);
106   s1.f3(s); assert(called == 2);
108   S2<S> s2;
109   s2.f1(0); assert(called == 1);
110   s2.f2(s); assert(called == 2);
112   s2.f3(0); assert(called == 1);
113   s2.f3(s); assert(called == 2);
115   s2.h1(0); assert(called == 1);
116   s2.h2(s); assert(called == 2);
118   s2.h3(0); assert(called == 1);
119   s2.h3(s); assert(called == 2);
121   s2.g1(s, s); assert(called == 1);
122   s2.g2(s, s); assert(called == 2);
124   ptr(&s); assert(called == 1);
125   ptr(&cs); assert(called == 2);
127   ref(s); assert(called == 1);
128   ref(cs); assert(called == 2);
130   // Check forwarding problems
131   fwd_lvalue_ref(s);
132   fwd_const_lvalue_ref(cs);
133   fwd_rvalue_ref(S());
135   foo(0);
138 // Test that decl/def matching works.
140 void p(auto x) { called = 1; }
141 void p(C x) { called = 2; }
143 template<C T>
144   void S2<T>::h1(auto x) { called = 1; }
146 template<C T>
147   void S2<T>::h2(C x) { called = 2; }
149 template<C T>
150   void S2<T>::h3(auto x) { called = 1; }
152 template<C T>
153   void S2<T>::h3(C x) { called = 2; }
155 template<C T>
156   template<C U>
157     void S2<T>::g2(T t, U u) { called = 2; }