Mercurial > hg > CbC > CbC_gcc
comparison gcc/testsuite/g++.dg/cpp2a/concepts-fn1.C @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
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 |