145
|
1 // { dg-do compile { target c++2a } }
|
|
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>
|
|
29 int fn1(T t) { return 0; }
|
|
30
|
|
31 template<typename T>
|
|
32 requires False<T>
|
|
33 int fn2(T t) { return 0; }
|
|
34
|
|
35 void driver()
|
|
36 {
|
|
37 fn1(0); // OK
|
|
38 fn2(0); // { dg-error "" }
|
|
39 }
|
|
40
|
|
41 // Ordering
|
|
42
|
|
43 template<typename T>
|
|
44 concept Cf = requires (T t) { t.f(); };
|
|
45
|
|
46 template<typename T>
|
|
47 concept Cfg = Cf<T> && requires (T t) { t.g(); };
|
|
48
|
|
49 template<typename T>
|
|
50 concept Cf2 = requires (T t) { t.f(); };
|
|
51
|
|
52 template<typename T>
|
|
53 constexpr int algo(T t) { return 0; }
|
|
54
|
|
55 template<typename T> requires Cf<T>
|
|
56 constexpr int algo(T t) { return 1; }
|
|
57
|
|
58 template<typename T> requires Cfg<T>
|
|
59 constexpr int algo(T t) { return 2; }
|
|
60
|
|
61 template<typename T> requires Cf<T>
|
|
62 constexpr int ambig(T t) { return 1; }
|
|
63
|
|
64 template<typename T> requires Cf2<T>
|
|
65 constexpr int ambig(T t) { return 1; }
|
|
66
|
|
67 struct T1 {
|
|
68 void f() { }
|
|
69 };
|
|
70
|
|
71 struct T2 : T1 {
|
|
72 void g() { }
|
|
73 };
|
|
74
|
|
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 {
|
|
88 void f() requires Class<T> { }
|
|
89
|
|
90 template<typename U>
|
|
91 struct Inner
|
|
92 {
|
|
93 void g() requires Classes<T, U> { }
|
|
94 };
|
|
95
|
|
96 template<typename U> requires Classes<T, U> void h(U) { }
|
|
97 };
|
|
98
|
|
99 struct X { };
|
|
100
|
|
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
|
|
121 template<typename T> requires Class<T> void f1(T x) { }
|
|
122
|
|
123 // fn1-2.C -- Dependent checks
|
|
124 template<typename T>
|
|
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>
|
|
135 constexpr int f2(T x) { return 1; }
|
|
136
|
|
137 template<typename T>
|
|
138 requires EmptyClass<T>
|
|
139 constexpr int f2(T x) { return 2; }
|
|
140
|
|
141 template<typename T>
|
|
142 constexpr int f3(T x) requires Class<T> { return 1; }
|
|
143
|
|
144 template<typename T>
|
|
145 constexpr int f3(T x) requires EmptyClass<T> { return 2; }
|
|
146
|
|
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
|
|
158 template<typename T> requires Type<T> void ok(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
|
|
168 template<typename T> void g(T x) { }
|
|
169
|
|
170 void driver_3 ()
|
|
171 {
|
|
172 g(&ok<int>);
|
|
173 g(&err<int>); // { dg-error "no matches" }
|
|
174 }
|
|
175
|
|
176
|
|
177 struct S2 {
|
|
178 template<typename T> requires Type<T> int ok(T) { return 0; }
|
|
179 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>
|
|
192 constexpr int fn(T) { return 1; }
|
|
193
|
|
194 template<typename T>
|
|
195 requires EmptyClass<T>
|
|
196 constexpr int fn(T) { return 2; }
|
|
197
|
|
198 struct S3
|
|
199 {
|
|
200 template<typename T>
|
|
201 requires Class<T>
|
|
202 constexpr int fn(T) const { return 1; }
|
|
203
|
|
204 template<typename T>
|
|
205 requires EmptyClass<T>
|
|
206 constexpr int fn(T) const { return 2; }
|
|
207 };
|
|
208
|
|
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
|
|
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
|
|
246 template<typename T> requires Type<T> void def() { }
|
|
247 template<typename T> requires Type<T> void def() { } // { dg-error "redefinition" }
|
|
248
|