1 // { dg-do compile { target c++20 } }
2 // { dg-additional-options "-fconcepts-ts" }
4 // Basic tests using variable concepts.
7 concept bool Type = true;
10 concept bool False = false;
13 concept bool Class = __is_class(T);
16 concept bool EmptyClass = Class<T> && __is_empty(T);
18 template<typename T, typename U>
19 concept bool Classes = __is_class(T) && __is_class (U);
23 struct nonempty { int n; };
25 static_assert(Type<int>);
26 static_assert(False<int>); // { dg-error "static assertion failed" }
32 int fn1(T t) { return 0; }
36 int fn2(T t) { return 0; }
41 fn2(0); // { dg-error "" }
47 concept bool Cf = requires (T t) { t.f(); };
50 concept bool Cfg = Cf<T> && requires (T t) { t.g(); };
53 concept bool Cf2 = requires (T t) { t.f(); };
56 constexpr int algo(T t) { return 0; }
58 template<typename T> requires Cf<T>
59 constexpr int algo(T t) { return 1; }
61 template<typename T> requires Cfg<T>
62 constexpr int algo(T t) { return 2; }
64 template<typename T> requires Cf<T>
65 constexpr int ambig(T t) { return 1; }
67 template<typename T> requires Cf2<T>
68 constexpr int ambig(T t) { return 1; }
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" }
91 void f() requires Class<T> { }
96 void g() requires Classes<T, U> { }
99 template<typename U> requires Classes<T, U> void h(U) { }
109 s1.h(0); // { dg-error "no matching function" }
112 s2.f(); // { dg-error "no matching function" }
117 S<X>::Inner<int> si2;
118 si2.g(); // { dg-error "no matching function" }
121 // Check constraints on non-dependent arguments, even when in a
122 // dependent context.
124 template<typename T> requires Class<T> void f1(T x) { }
126 // fn1-2.C -- Dependent checks
130 f1(x); // Unchecked dependent arg.
131 f1(empty{}); // Checked non-dependent arg, but OK
132 f1(0); // { dg-error "" }
138 constexpr int f2(T x) { return 1; }
141 requires EmptyClass<T>
142 constexpr int f2(T x) { return 2; }
145 constexpr int f3(T x) requires Class<T> { return 1; }
148 constexpr int f3(T x) requires EmptyClass<T> { return 2; }
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);
160 // fn8.C -- Address of overloaded functions
161 template<typename T> requires Type<T> void ok(T) { }
162 template<typename T> requires Class<T> void err(T) { }
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" }
171 template<typename T> void g(T x) { }
176 g(&err<int>); // { dg-error "no match" }
181 template<typename T> requires Type<T> int ok(T) { return 0; }
182 template<typename T> requires Class<T> int err(T) { return 0; }
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" }
192 // fn9.C -- Ordering with function address
195 constexpr int fn(T) { return 1; }
198 requires EmptyClass<T>
199 constexpr int fn(T) { return 2; }
205 constexpr int fn(T) const { return 1; }
208 requires EmptyClass<T>
209 constexpr int fn(T) const { return 2; }
220 constexpr auto p1 = &fn<X>; // Empty f
221 static_assert (p1(x) == 2);
223 constexpr auto p2 = &fn<Y>; // Class f
224 static_assert(p2(y) == 1);
226 constexpr auto p3 = &S3::fn<X>; // Empty f
227 static_assert((s.*p3)(x) == 2);
229 constexpr auto p4 = &S3::fn<Y>; // Empty f
230 static_assert((s.*p4)(y) == 1);
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>;
243 f3<int>(); // { dg-error "call of overload | ambiguous" }
246 template<template<typename T> requires true class X> void f4();
247 template<template<typename T> class X> void f4(); // OK: different declarations
249 template<typename T> requires Type<T> void def() { }
250 template<typename T> requires Type<T> void def() { } // { dg-error "redefinition" }