Thanks to partial ordering of function templates, the following seems to be unambiguous:
template <class T> void f(T*) {
cout << "T*" << endl;
}
template <class T> void f(const T*) {
cout << "const T*" << endl;
}
int main(){
int *p = nullptr;
f(p);
}
T
is deduced as int
in both cases, and both specializations are viable, with the second requring an implicit qualification conversion from int *
to const int*
. Both are added to the overload set.
To find the best viable function, we turn to partial ordering. We synthesize new types for each and get void f(X*)
and void f(const Y*)
. Then we do type deduction between the two. [temp.deduct.partial]¶8:
Using the resulting types P and A, the deduction is then done as described in 17.8.2.5. (...) If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template.
Does deduction succeed for template <class T> void f(T*)
given const Y*
? Yes, with T=const Y
.
Does deduction succeed for template <class T> void f(const T*)
given X*
? Yes, with T=X
(requiring an implicit qualification conversion).
So X and Y are both at least as specialized as the other, which means that both specializations are at least as specialized as the other, which means that the call is ambiguous.
Except that it isn't, so where did I go wrong above?
const
is not an exact match, so the exact match is preferred. – NathanOliverp
is aint*
not aconst int*
– 463035818_is_not_a_number