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 example
compound-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