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)29int fn1(T t) { return 0; } 30 31 template<typename T> 32 requires False<T> fn2(T t)33int fn2(T t) { return 0; } 34 driver()35void driver() 36 { 37 fn1(0); // OK 38 fn2(0); // { dg-error "" } 39 } 40 41 // Ordering 42 43 template<typename T> requires(T t)44concept Cf = requires (T t) { t.f(); }; 45 46 template<typename T> requires(T t)47concept Cfg = Cf<T> && requires (T t) { t.g(); }; 48 49 template<typename T> requires(T t)50concept Cf2 = requires (T t) { t.f(); }; 51 52 template<typename T> algo(T t)53constexpr int algo(T t) { return 0; } 54 55 template<typename T> requires Cf<T> algo(T t)56constexpr int algo(T t) { return 1; } 57 58 template<typename T> requires Cfg<T> algo(T t)59constexpr int algo(T t) { return 2; } 60 61 template<typename T> requires Cf<T> ambig(T t)62constexpr int ambig(T t) { return 1; } 63 64 template<typename T> requires Cf2<T> ambig(T t)65constexpr 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()75void 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()101void 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)121template<typename T> requires Class<T> void f1(T x) { } 122 123 // fn1-2.C -- Dependent checks 124 template<typename T> caller_1(T x)125void 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)135constexpr int f2(T x) { return 1; } 136 137 template<typename T> 138 requires EmptyClass<T> f2(T x)139constexpr int f2(T x) { return 2; } 140 141 template<typename T> f3(T x)142constexpr int f3(T x) requires Class<T> { return 1; } 143 144 template<typename T> f3(T x)145constexpr int f3(T x) requires EmptyClass<T> { return 2; } 146 driver_2()147void 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)158template<typename T> requires Type<T> void ok(T) { } err(T)159template<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)168template<typename T> void g(T x) { } 169 driver_3()170void 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)192constexpr int fn(T) { return 1; } 193 194 template<typename T> 195 requires EmptyClass<T> fn(T)196constexpr 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()209void 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()238void 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()246template<typename T> requires Type<T> void def() { } def()247template<typename T> requires Type<T> void def() { } // { dg-error "redefinition" } 248 249