A template declaration ([temp.pre])
or templated function declaration ([dcl.fct])
can be constrained by the use of a *requires-clause*.

This allows the specification of constraints for that declaration as
an expression:

Constraints can also be associated with a declaration through the use of
*type-constraint**s*
in a *template-parameter-list* or parameter-type-list.

Each of these forms introduces additional *constraint-expression**s*
that are used to constrain the declaration.

A declaration's *associated constraints* are defined as follows:

- Otherwise, if there is a single introduced
*constraint-expression*, the associated constraints are the normal form of that expression. - Otherwise, the associated constraints are the normal form of a logical AND expression whose operands are in the following order:
- the
*constraint-expression*introduced by each*type-constraint*([temp.param]) in the declaration's*template-parameter-list*, in order of appearance, and - the
*constraint-expression*introduced by a*requires-clause*following a*template-parameter-list*([temp.pre]), and - the
*constraint-expression*introduced by each*type-constraint*in the parameter-type-list of a function declaration, and - the
*constraint-expression*introduced by a trailing*requires-clause*([dcl.decl]) of a function declaration ([dcl.fct]).

- the

The formation of the associated constraints
establishes the order in which constraints are instantiated when checking
for satisfaction ([temp.constr.constr]).

[*Example 1*: template<typename T> concept C = true;
template<C T> void f1(T);
template<typename T> requires C<T> void f2(T);
template<typename T> void f3(T) requires C<T>;

template<typename T> concept C1 = true;
template<typename T> concept C2 = sizeof(T) > 0;
template<C1 T> void f4(T) requires C2<T>;
template<typename T> requires C1<T> && C2<T> void f5(T);

template<C1 T> requires C2<T> void f6();
template<C2 T> requires C1<T> void f7();
— *end example*]

When determining whether a given introduced
*constraint-expression* of a declaration
in an instantiated specialization of a templated class
is equivalent ([temp.over.link]) to the corresponding
*constraint-expression* of a declaration
outside the class body,
is instantiated.

If the instantiation results in an invalid expression,
the *constraint-expression**s* are not equivalent.

[*Example 2*: template <class T> concept C = true;
template <class T> struct A {
template <class U> U f(U) requires C<typename T::type>; // #1
template <class U> U f(U) requires C<T>; // #2
};
template <> template <class U>
U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
*end example*]

Substituting int for T in C<typename T::type>
produces an invalid expression, so the specialization does not match #1.

Substituting int for T in C<T> produces C<int>,
which is equivalent to the *constraint-expression* for the specialization,
so it does match #2.

—