1 // { dg-do compile { target c++20 } }
2 // { dg-additional-options "-fconcepts-ts" }
3 
4 // Basic tests using function concepts.
5 
6 template<typename T>
Type()7 concept bool Type() { return true; }
8 
9 template<typename T>
False()10 concept bool False() { return false; }
11 
12 template<typename T>
Class()13 concept bool Class() { return __is_class(T); }
14 
15 template<typename T>
EmptyClass()16 concept bool EmptyClass() { return Class<T>() && __is_empty(T); }
17 
18 template<typename T, typename U>
Classes()19 concept bool Classes() { return __is_class(T) && __is_class (U); }
20 
21 struct empty { };
22 
23 struct nonempty { int n; };
24 
25 static_assert(Type<int>());
26 static_assert(False<int>()); // { dg-error "static assertion failed" }
27 
28 // Basic checks
29 
30 template<typename T>
requires(Type<T> ())31   requires (Type<T>())
32 int fn1(T t) { return 0; }
33 
34 template<typename T>
requires(False<T> ())35   requires (False<T>())
36 int fn2(T t) { return 0; }
37 
driver()38 void driver()
39 {
40   fn1(0); // OK
41   fn2(0); // { dg-error "" }
42 }
43 
44 // Ordering
45 
46 template<typename T>
Cf()47 concept bool Cf() { return requires (T t) { t.f(); }; }
48 
49 template<typename T>
Cfg()50 concept bool Cfg() { return Cf<T>() && requires (T t) { t.g(); }; }
51 
52 template<typename T>
Cf2()53 concept bool Cf2() { return requires (T t) { t.f(); }; }
54 
55 template<typename T>
algo(T t)56 constexpr int algo(T t) { return 0; }
57 
requires(Cf<T> ())58 template<typename T> requires (Cf<T>())
59 constexpr int algo(T t) { return 1; }
60 
requires(Cfg<T> ())61 template<typename T> requires (Cfg<T>())
62 constexpr int algo(T t) { return 2; }
63 
requires(Cf<T> ())64 template<typename T> requires (Cf<T>())
65 constexpr int ambig(T t) { return 1; }
66 
requires(Cf2<T> ())67 template<typename T> requires (Cf2<T>())
68 constexpr int ambig(T t) { return 1; }
69 
70 struct T1 {
fT171   void f() { }
72 };
73 
74 struct T2 : T1 {
gT275   void g() { }
76 };
77 
driver_0()78 void driver_0()
79 {
80   T1 x;
81   T2 y;
82   static_assert(algo(0) == 0);
83   static_assert(algo(x) == 1);
84   static_assert(algo(y) == 2);
85   ambig(x); // { dg-error "call of overload | is ambiguous" }
86 }
87 
88 template<typename T>
89 struct S
90 {
fS91   void f() requires (Class<T>()) { }
92 
93   template<typename U>
94   struct Inner
95   {
gS::Inner96     void g() requires (Classes<T, U>()) { }
97   };
98 
requiresS99   template<typename U> requires (Classes<T, U>()) void h(U) { }
100 };
101 
102 struct X { };
103 
driver_1()104 void driver_1()
105 {
106   S<X> s1;
107   s1.f(); // OK
108   s1.h(s1); // OK
109   s1.h(0); // { dg-error "no matching function" }
110 
111   S<int> s2;
112   s2.f(); // { dg-error "no matching function" }
113 
114   S<X>::Inner<X> si1;
115   si1.g();
116 
117   S<X>::Inner<int> si2;
118   si2.g(); // { dg-error "no matching function" }
119 }
120 
121 // Check constraints on non-dependent arguments, even when in a
122 // dependent context.
123 
requires(Class<T> ())124 template<typename T> requires (Class<T>()) void f1(T x) { }
125 
126 // fn1-2.C -- Dependent checks
127 template<typename T>
caller_1(T x)128 void caller_1(T x)
129 {
130   f1(x); // Unchecked dependent arg.
131   f1(empty{}); // Checked non-dependent arg, but OK
132   f1(0); // { dg-error "" }
133 }
134 
135 // fn3.c -- Ordering
136 template<typename T>
requires(Class<T> ())137   requires (Class<T>())
138 constexpr int f2(T x) { return 1; }
139 
140 template<typename T>
requires(EmptyClass<T> ())141   requires (EmptyClass<T>())
142 constexpr int f2(T x) { return 2; }
143 
144 template<typename T>
f3(T x)145 constexpr int f3(T x) requires (Class<T>()) { return 1; }
146 
147 template<typename T>
f3(T x)148 constexpr int f3(T x) requires (EmptyClass<T>()) { return 2; }
149 
driver_2()150 void driver_2()
151 {
152   f2(0); // { dg-error "no matching function" }
153   static_assert (f2(empty{}) == 2);
154   static_assert (f2(nonempty{}) == 1);
155   f3(0); // { dg-error "no matching function" }
156   static_assert (f3(empty{}) == 2);
157   static_assert (f3(nonempty{}) == 1);
158 }
159 
160 // fn8.C -- Address of overloaded functions
requires(Type<T> ())161 template<typename T> requires (Type<T>()) void ok(T) { }
requires(Class<T> ())162 template<typename T> requires (Class<T>()) void err(T) { }
163 
164 auto p1 = &ok<int>;
165 auto p2 = &err<int>; // { dg-error "" }
166 void (*p3)(int) = &ok<int>;
167 void (*p4)(int) = &err<int>; // { dg-error "no matches" }
168 void (*p5)(int) = &ok;
169 void (*p6)(int) = &err; // { dg-error "no matches" }
170 
g(T x)171 template<typename T> void g(T x) { }
172 
driver_3()173 void driver_3 ()
174 {
175   g(&ok<int>);
176   g(&err<int>); // { dg-error "no match" }
177 }
178 
179 
180 struct S2 {
requiresS2181   template<typename T> requires (Type<T>()) int ok(T) { return 0; }
requiresS2182   template<typename T> requires (Class<T>()) int err(T) { return 0; }
183 };
184 
185 auto p7 = &S2::ok<int>;
186 auto p8 = &S2::err<int>; // { dg-error "" }
187 int (S2::*p9)(int) = &S2::ok<int>;
188 int (S2::*p10)(int) = &S2::err<int>; // { dg-error "no matches" }
189 int (S2::*p11)(int) = &S2::ok;
190 int (S2::*p12)(int) = &S2::err; // { dg-error "no matches" }
191 
192 // fn9.C -- Ordering with function address
193 template<typename T>
requires(Class<T> ())194   requires (Class<T>())
195 constexpr int fn(T) { return 1; }
196 
197 template<typename T>
requires(EmptyClass<T> ())198   requires (EmptyClass<T>())
199 constexpr int fn(T) { return 2; }
200 
201 struct S3
202 {
203   template<typename T>
requiresS3204     requires (Class<T>())
205   constexpr int fn(T) const { return 1; }
206 
207   template<typename T>
requiresS3208     requires (EmptyClass<T>())
209   constexpr int fn(T) const { return 2; }
210 };
211 
driver_5()212 void driver_5 () {
213   struct X { };
214   struct Y { X x; };
215 
216   constexpr X x;
217   constexpr Y y;
218   constexpr S3 s;
219 
220   constexpr auto p1 = &fn<X>; // Empty f
221   static_assert (p1(x) == 2);
222 
223   constexpr auto p2 = &fn<Y>; // Class f
224   static_assert(p2(y) == 1);
225 
226   constexpr auto p3 = &S3::fn<X>; // Empty f
227   static_assert((s.*p3)(x) == 2);
228 
229   constexpr auto p4 = &S3::fn<Y>; // Empty f
230   static_assert((s.*p4)(y) == 1);
231 }
232 
233 
234 // Redeclarations
235 
236 // FIXME: This should be a diagnosable error. The programmer has moved
237 // the requirements from the template-head to the declarator.
238 template<typename T> requires (Type<T>()) void f3();
239 template<typename T> void f3() requires (Type<T>());
240 
driver_4()241 void driver_4()
242 {
243   f3<int>(); // { dg-error "call of overload | ambiguous" }
244 }
245 
246 template<template<typename T> requires true class X> void f4();
247 template<template<typename T> class X> void f4(); // OK: different declarations
248 
requires(Type<T> ())249 template<typename T> requires (Type<T>()) void def() { }
requires(Type<T> ())250 template<typename T> requires (Type<T>()) void def() { } // { dg-error "redefinition" }
251 
252 // fn-concept1.C
253 
254 template<typename T>
Tuple()255 concept bool Tuple() { // { dg-error "multiple statements" }
256   static_assert(T::value, "");
257   return true;
258 }
259 
260 void f(Tuple&);
261