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)32int fn1(T t) { return 0; } 33 34 template<typename T> 35 requires False<T> fn2(T t)36int fn2(T t) { return 0; } 37 driver()38void driver() 39 { 40 fn1(0); // OK 41 fn2(0); // { dg-error "" } 42 } 43 44 // Ordering 45 46 template<typename T> requires(T t)47concept bool Cf = requires (T t) { t.f(); }; 48 49 template<typename T> requires(T t)50concept bool Cfg = Cf<T> && requires (T t) { t.g(); }; 51 52 template<typename T> requires(T t)53concept bool Cf2 = requires (T t) { t.f(); }; 54 55 template<typename T> algo(T t)56constexpr int algo(T t) { return 0; } 57 58 template<typename T> requires Cf<T> algo(T t)59constexpr int algo(T t) { return 1; } 60 61 template<typename T> requires Cfg<T> algo(T t)62constexpr int algo(T t) { return 2; } 63 64 template<typename T> requires Cf<T> ambig(T t)65constexpr int ambig(T t) { return 1; } 66 67 template<typename T> requires Cf2<T> ambig(T t)68constexpr 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()78void 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()104void 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)124template<typename T> requires Class<T> void f1(T x) { } 125 126 // fn1-2.C -- Dependent checks 127 template<typename T> caller_1(T x)128void 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)138constexpr int f2(T x) { return 1; } 139 140 template<typename T> 141 requires EmptyClass<T> f2(T x)142constexpr int f2(T x) { return 2; } 143 144 template<typename T> f3(T x)145constexpr int f3(T x) requires Class<T> { return 1; } 146 147 template<typename T> f3(T x)148constexpr int f3(T x) requires EmptyClass<T> { return 2; } 149 driver_2()150void 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)161template<typename T> requires Type<T> void ok(T) { } err(T)162template<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)171template<typename T> void g(T x) { } 172 driver_3()173void driver_3 () 174 { 175 g(&ok<int>); 176 g(&err<int>); // { dg-error "no matches" } 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)195constexpr int fn(T) { return 1; } 196 197 template<typename T> 198 requires EmptyClass<T> fn(T)199constexpr 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()212void 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()241void 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()249template<typename T> requires Type<T> void def() { } def()250template<typename T> requires Type<T> void def() { } // { dg-error "redefinition" } 251 252