There are multiple questions asked here and here regarding partial ordering. But they all cover the process of partial ordering and when it occurs.
The point of my question lies in this paragraph on the standard:
If multiple function templates share a name, the use of that name can be ambiguous because template argument deduction ([temp.deduct]) may identify a specialization for more than one function template. Partial ordering of overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization refers:
- (1.1) during overload resolution for a call to a function template specialization ([over.match.best]);
- (1.2) when the address of a function template specialization is taken;
- (1.3) when a placement operator delete that is a function template specialization is selected to match a placement operator new ([basic.stc.dynamic.deallocation], [expr.new]);
- (1.4) when a friend function declaration, an explicit instantiation or an explicit specialization refers to a function template specialization.
It's clear from this paragraph that partial ordering is used in the above contexts to select the function template to which a function template specialization refers.
So if I have example:
template <class T> void f(T); // T1
template <class T> void f(T*); // T2
f((int*)0); // bullet 1.1 applies
// the implicit specializations could be:
// template <> void f<int*>(int*); // F1
// template <> void f<int>(int*); // F2
From the bold part above, and in my example, partial ordering is just used to ensure that F1 refers to T1 and F2 refers to T2 without any ambigiuty. Right?
Does this the only use of partial ordering? does it used to select the more specialized template?
EDIT
I just added another example to ensure that the order of events is correct.
template <class T> void f(const T&); // T1:
template <class T> void f(T*); // T2:
f((int*)0);
// the compiler may be generates:
// template <> void f(int* const&); // F1
// template <> void f(int*); // F2
1- because the call f((int*)0)
matches the bullet 1.1
, partial ordering occurs.
2- partial ordering ensures that the name of specialization F1
does match more than function template. That's F1 refers only T1. The same check is occur for F2: F2 refers to T2 only.
3- The overload set contains F1 and F2. Both ICS(F1) and ICS(F2) are identity conversions. Here neither rule in [over.ics.rank]/3/3.2 is applied.
4- Then the compiler goes to the next step to check the rules defined in [over.match.best.general]/2. Bullet 2.5 is applied since F1 and F2 are function template specializations. Then partial ordering rules ([temp.func.order]) are applied to check the more specialized template.
These steps I follow when I encounter a call to an overloaded template. Do these steps are true? Does the order of these steps are consistent?
Do steps 1 and 2 are redundant?