A *requires-expression* provides a concise way to express
requirements on template arguments
that can be checked by name lookup
or by checking properties of types and expressions.

[*Example 1*: *end example*]

A common use of *requires-expression**s* is to define
requirements in concepts such as the one below:
template<typename T>
concept R = requires (T i) {
typename T::type;
{*i} -> std::convertible_to<const typename T::type&>;
};

A *requires-expression* can also be used in a
*requires-clause* ([temp.pre]) 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*.

— A *requires-expression* may introduce local parameters using a
*parameter-declaration-clause* ([dcl.fct]).

A local parameter of a *requires-expression* shall not have a
default argument.

Each name introduced by a local parameter is in scope from the point
of its declaration until the closing brace of the
*requirement-body*.

These parameters have no linkage, storage, or lifetime; they are only used
as notation for the purpose of defining *requirement**s*.

The *parameter-declaration-clause* of a
*requirement-parameter-list*
shall not terminate with an ellipsis.

[*Example 2*: template<typename T>
concept C = requires(T t, ...) { // error: terminates with an ellipsis
t;
};
— *end example*]

These *requirement**s* may refer to local
parameters, template parameters, and any other declarations visible from the
enclosing context.

The substitution of template arguments into a *requires-expression*
may result in the formation of invalid types or expressions in its
*requirement**s* or the violation of the semantic constraints of those *requirement**s*.

In such cases, the *requires-expression* evaluates to false;
it does not cause the program to be ill-formed.

The substitution and semantic constraint checking
proceeds in lexical order and stops when a condition that
determines the result of the *requires-expression* is encountered.

If substitution (if any) and semantic constraint checking succeed,
the *requires-expression* evaluates to true.

[*Note 1*: *end note*]

If a *requires-expression* contains invalid types or expressions in
its *requirement**s*, and it does not appear within the declaration of a templated
entity, then the program is ill-formed.

—
If the substitution of template arguments into a *requirement*
would always result in a substitution failure, the program is ill-formed;
no diagnostic required.

[*Example 3*: template<typename T> concept C =
requires {
new int[-(int)sizeof(T)]; // ill-formed, no diagnostic required
};
— *end example*]

[*Note 1*: *end note*]

The enclosing *requires-expression* will evaluate to false
if substitution of template arguments into the *expression* fails.

— [*Example 1*: template<typename T> concept C =
requires (T a, T b) {
a + b; // C<T> is true if a + b is a valid expression
};
— *end example*]

[*Note 2*: — *end note*]

A *type-requirement* asserts the validity of a type.

[*Note 1*: *end note*]

The enclosing *requires-expression* will evaluate to false
if substitution of template arguments fails.

— [*Example 1*: 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*]

A *type-requirement* that names a class template specialization
does not require that type to be complete ([basic.types]).

Substitution
of template arguments (if any) and verification of
semantic properties proceed in the following order:

- Substitution of template arguments (if any) into the
*expression*is performed. - If the noexcept specifier is present, E shall not be a potentially-throwing expression ([except.spec]).
- If the
*return-type-requirement*is present, then:- Substitution of template arguments (if any) into the
*return-type-requirement*is performed. - The immediately-declared constraint ([temp.param]) of the
*type-constraint*for decltype((E)) shall be satisfied.

[*Example 2*: template<typename T> concept C1 = requires(T x) {
{x++};
};

template<typename T> concept C2 = requires(T x) {
{*x} -> std::same_as<typename T::inner>;
};

The *compound-requirement* in C2
requires that *x is a valid expression,
that typename T::inner is a valid type, and
that std::same_as<decltype((*x)), typename T::inner> is satisfied.

template<typename T> concept C3 =
requires(T x) {
{g(x)} noexcept;
};

The *compound-requirement* in C3
requires that g(x) is a valid expression and
that g(x) is non-throwing.

— A *nested-requirement* can be used
to specify additional constraints in terms of local parameters.

The *constraint-expression*
shall be satisfied ([temp.constr.decl])
by the substituted template arguments, if any.

Substitution of template arguments into a *nested-requirement*
does not result in substitution into the *constraint-expression*
other than as specified in [temp.constr.constr].

[*Example 1*: *end example*]

template<typename U> concept C = sizeof(U) == 1;
template<typename T> concept D = requires (T t) {
requires C<decltype (+t)>;
};
D<T> is satisfied if sizeof(decltype (+t)) == 1 ([temp.constr.atomic]).

— [*Example 2*: template<typename T> concept C = requires (T a) {
requires sizeof(a) == 4; // OK
requires a == 0; // error: evaluation of a constraint variable
};
— *end example*]