requires-expression: requires requirement-parameter-list requirement-body
requirement-parameter-list: ( parameter-declaration-clause )
requirement-body: { requirement-seq }
requirement-seq: requirement requirement-seq requirement
requirement: simple-requirement type-requirement compound-requirement nested-requirement
template<typename T>
concept R = requires (T i) {
typename T::type;
{*i} -> const typename T::type&;
};
A requires-expression can also be used in a
requires-clause as a way of writing ad hoc
constraints on template arguments such as the one below:
template<typename T>
requires requires (T x) { x + x; }
T add(T a, T b) { return a + b; }
The first requires introduces the
requires-clause, and the second
introduces the requires-expression.
template<typename T>
concept C = requires(T t, ...) { // error: terminates with an ellipsis
t;
}; — end example
template<typename T> concept C =
requires {
new int[-(int)sizeof(T)]; // ill-formed, no diagnostic required
}; — end examplesimple-requirement: expression ;
template<typename T> concept C =
requires (T a, T b) {
a + b; // C<T> is true if a + b is a valid expression
}; — end exampletype-requirement: typename nested-name-specifier type-name ;
template<typename T, typename T::type = 0> struct S;
template<typename T> using Ref = T&;
template<typename T> concept C = requires {
typename T::inner; // required nested member name
typename S<T>; // required class template specialization
typename Ref<T>; // required alias template substitution, fails if T is void
}; — end examplecompound-requirement: { expression } noexcept return-type-requirement ;
return-type-requirement: trailing-return-type -> cv-qualifier-seq constrained-parameter cv-qualifier-seq abstract-declarator
template<typename T> concept C1 = requires(T x) {
{x++};
};
template<typename T> concept C2 = requires(T x) {
{*x} -> typename T::inner;
};
template<typename T, typename U> concept C3 = requires (T t, U u) {
t == u;
};
template<typename T> concept C4 = requires(T x) {
{*x} -> C3<int> const&;
}; template<C3<int> X> void f(X const&);In this case, deduction only succeeds if an expression of the type deduced for X can be compared to an int with the == operator.
template<typename T> concept C5 =
requires(T x) {
{g(x)} noexcept;
};nested-requirement: requires constraint-expression ;
template<typename U> concept C = sizeof(U) == 1;
template<typename T> concept D = requires (T t) {
requires C<decltype (+t)>;
}; — end example
template<typename T> concept C = requires (T a) {
requires sizeof(a) == 4; // OK
requires a == 0; // error: evaluation of a constraint variable
} — end example