blob: 03668d34384d728d62f1aa25d198c953fcf2d325 [file] [log] [blame]
// { dg-do compile { target c++20 } }
template<typename T>
concept Class = __is_class(T);
// Allow a requires-expression with no parms.
template<typename T>
concept C = requires { typename T::type; };
void f1(int a) requires true; // { dg-error "non-templated" }
auto f2(int a) -> bool requires true; // { dg-error "non-templated" }
auto f3(int a) requires true -> bool; // { dg-error "" } requires-clause precedes trailing-return-type
typedef void fn_t() requires true; // { dg-error "typedef" }
void (*pf)() requires true; // { dg-error "non-function" }
void (*fn(int))() requires false; // { dg-error "return type" }
void g(int (*)() requires true); // { dg-error "parameter|non-function" }
auto* p = new (void(*)(char) requires true); // { dg-error "type-id" }
void f4(auto a) requires Class<decltype(a)> { }
void f5(auto a) requires requires (decltype(a) x) { -x; } { } // { dg-message "in requirements" }
struct Test {
void f(auto a) requires Class<decltype(a)>;
} test;
void driver_1() {
struct S { } s;
f4(s);
f5(0);
f5((void*)0); // { dg-error "" }
test.f(s);
}
void Test::f(auto a) requires Class<decltype(a)> { }
template<bool B> requires B struct S0; // OK
template<int N> requires N struct S1 { }; // { dg-error "does not have type" }
S1<1> x0; // { dg-error "template constraint failure|does not have type" }
template<int N> requires N == 0 struct S2 { }; // { dg-error "does not have type|must be enclosed" }
template<int N> requires (N == 0) struct S3 { }; // OK
template<typename T, T X> requires X struct S4 { }; // { dg-error "bool" }
S4<int, 0> x1; // { dg-error "template constraint failure" }
S4<bool, true> x2; // OK
S4<bool, false> x3; // { dg-error "template constraint failure" }
// req11.C
template<typename T>
concept Streamable = requires (T t) { t; };
template<typename T>
concept Range = requires (T t) { t; };
// FIXME: There are two syntax errors here when there should be
// just one.Note that !Range<T> is not a primary-expression and needs to
// be wrapped in parens to be syntactically valid.
template<class T>
requires Streamable<T> && !Range<T> // { dg-error "must be enclosed" }
void print1(const T& x) { }
template<class T>
requires Streamable<T> && (!Range<T>)
void print2(const T& x) { }
void driver_3()
{
print2("hello"); // { dg-error "" }
}