When a template is used in a context that requires an instantiation of
the template,
it is necessary to determine whether the instantiation is to be generated
using the primary template or one of the partial specializations.
This is done by matching the template arguments of the template
specialization with the template argument lists of the partial
specializations.
If more than one matching partial specialization is found,
the partial order rules ([temp.spec.partial.order]) are used to determine
whether one of the partial specializations is more specialized than the
others.
If such a partial specialization exists,
the instantiation is generated from that partial specialization;
otherwise, the use of the template is ambiguous and the program is ill-formed.
A partial specialization matches a given actual template argument
list if the template arguments of the partial specialization can be
deduced from the actual template argument list,
and the deduced template arguments satisfy the associated constraints
of the partial specialization, if any.
[Example 1: template<class T1, class T2, int I>class A {}; // #1template<class T, int I>class A<T, T*, I>{}; // #2template<class T1, class T2, int I>class A<T1*, T2, I>{}; // #3template<class T>class A<int, T*, 5>{}; // #4template<class T1, class T2, int I>class A<T1, T2*, I>{}; // #5
A<int, int, 1> a1; // uses #1
A<int, int*, 1> a2; // uses #2, T is int, I is 1
A<int, char*, 5> a3; // uses #4, T is char
A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1
A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 — end example]
[Example 2: template<typename T>concept C =requires(T t){ t.f(); };
template<typename T>struct S {}; // #1template<C T>struct S<T>{}; // #2struct Arg {void f(); };
S<int> s1; // uses #1; the constraints of #2 are not satisfied
S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized — end example]
If the template arguments of a partial specialization cannot be deduced
because of the structure of its template-parameter-list
and the template-id,
the program is ill-formed.
[Example 3: template<int I, int J>struct A {};
template<int I>struct A<I+5, I*2>{}; // errortemplate<int I>struct A<I, I>{}; // OKtemplate<int I, int J, int K>struct B {};
template<int I>struct B<I, I*2, 2>{}; // OK — end example]
In a name that refers to a specialization of a class or variable template
(e.g., A<int, int, 1>),
the argument list shall match the template parameter list of the primary
template.
The template arguments of a partial specialization are deduced from the arguments
of the primary template.