13 Templates [temp]

13.5 Template constraints [temp.constr]

13.5.3 Constrained declarations [temp.constr.decl]

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-constraints in a template-parameter-list or parameter-type-list.
Each of these forms introduces additional constraint-expressions that are used to constrain the declaration.
A declaration's associated constraints are defined as follows:
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>;
The functions f1, f2, and f3 have the associated constraint 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);
The associated constraints of f4 and f5 are C1<T> C2<T>.
template<C1 T> requires C2<T> void f6(); template<C2 T> requires C1<T> void f7();
The associated constraints of f6 are C1<T> C2<T>, and those of f7 are C2<T> C1<T>.
— 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-expressions are not equivalent.
[Note 1:
This can happen when determining which member template is specialized by an explicit specialization declaration.
— end note]
[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
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.
— end example]