13 Templates [temp]

13.5 Template constraints [temp.constr]

13.5.2 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:
constraint-expression:
	logical-or-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
:
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
:
This can happen when determining which member template is specialized by an explicit specialization declaration.
— end note
 ]
Example
:
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
 ]