#include <iostream>
template <class U, class T>
void foo(U&, T&)
{
std::cout << "first";
}
template <class T>
void foo(int&, const T&)
{
std::cout << "second";
}
int main()
{
int a;
double g = 2.;
foo(a, g); // prints "first"
return 0;
}
To call the second foo
overload, the compiler needs to perform only one template type deduction, but for the first overload, it needs to perform two. Can you please explain why the first overload is called?
Overload resolution is done in multiple steps.
First, through name lookup, we select the list of viable candidates. In this case, that is:
Next, we determine the conversion sequence necessary for each argument for each viable candidate. This is [over.ics.rank]:
For the first call, the conversion sequence is (Identity, Identity). For the second call, the conversion sequence is (Identity, Identity). So we're equal there. Neither of those bullet points distinguish the two calls. So we move on.
Irrelevant.
Nope.
Qualification conversion is a pointer thing, nope.
In this case, the first overload takes its second argument as
double&
while the second overload takes aconst double&
. The former is less cv-qualified than the latter, so we stop here - preferringfoo(U&,T&)
.Only after the steps to determine which conversion sequence is better do we get to the step that the more specialized template is preferred. The full rule ordering in [over.match.best] is:
That's what we just went through.
That's why we pick
foo(U&, T&)
. If you remove theconst
, however, then both conversion sequences are identical across all steps - so at that point, the more specialized template (foo(int&, T&)
) would win.Note that more specialized is the very last mechanism to determine best candidate. It's the most final of tie breakers.
Also note that the number of template deductions is irrelevant. It may matter in selecting between overload that is a template and an overload that is not a template - but it does not matter in selecting between an overload that has x template parameters and an overload that has y > x template parameters.