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