1 // { dg-do compile { target c++2a } }
2 // { dg-additional-options "-fconcepts-ts" }
3 
4 // Basic tests using variable concepts.
5 
6 template<typename T>
7 concept bool Type = true;
8 
9 template<typename T>
10 concept bool False = false;
11 
12 template<typename T>
13 concept bool Class = __is_class(T);
14 
15 template<typename T>
16 concept bool EmptyClass = Class<T> && __is_empty(T);
17 
18 template<typename T, typename U>
19 concept bool Classes = __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>
31   requires Type<T>
fn1(T t)32 int fn1(T t) { return 0; }
33 
34 template<typename T>
35   requires False<T>
fn2(T 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>
requires(T t)47 concept bool Cf = requires (T t) { t.f(); };
48 
49 template<typename T>
requires(T t)50 concept bool Cfg = Cf<T> && requires (T t) { t.g(); };
51 
52 template<typename T>
requires(T t)53 concept bool Cf2 = requires (T t) { t.f(); };
54 
55 template<typename T>
algo(T t)56 constexpr int algo(T t) { return 0; }
57 
58 template<typename T> requires Cf<T>
algo(T t)59 constexpr int algo(T t) { return 1; }
60 
61 template<typename T> requires Cfg<T>
algo(T t)62 constexpr int algo(T t) { return 2; }
63 
64 template<typename T> requires Cf<T>
ambig(T t)65 constexpr int ambig(T t) { return 1; }
66 
67 template<typename T> requires Cf2<T>
ambig(T 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 
hS99   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 
f1(T x)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>
137   requires Class<T>
f2(T x)138 constexpr int f2(T x) { return 1; }
139 
140 template<typename T>
141   requires EmptyClass<T>
f2(T x)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
ok(T)161 template<typename T> requires Type<T> void ok(T) { }
err(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 {
okS2181   template<typename T> requires Type<T> int ok(T) { return 0; }
errS2182   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>
194   requires Class<T>
fn(T)195 constexpr int fn(T) { return 1; }
196 
197 template<typename T>
198   requires EmptyClass<T>
fn(T)199 constexpr int fn(T) { return 2; }
200 
201 struct S3
202 {
203   template<typename T>
204     requires Class<T>
fnS3205   constexpr int fn(T) const { return 1; }
206 
207   template<typename T>
208     requires EmptyClass<T>
fnS3209   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 
def()249 template<typename T> requires Type<T> void def() { }
def()250 template<typename T> requires Type<T> void def() { } // { dg-error "redefinition" }
251 
252