Igor R. Igor R. - 3 months ago 9
C++ Question

Overload resolution and explicit template arguments

The following code prints "func 2".

Why does the compiler treat the second template as a better match, in presence of explicit (not deduced) template arguments? Why is there no ambiguity?

I'd appreciate quotations from the C++ standard.

#include <iostream>

template<class T>
struct identity
{
typedef T type;
};

template<class T>
void func(T)
{
std::cout << "func 1\n";
}

template<class T>
void func(typename identity<T>::type)
{
std::cout << "func 2\n";
}

int main()
{
func<int>(1);
}

Answer

Both candidates are viable and take identical arguments, so the overload resolution process falls back to the last tiebreaker: partial ordering of function templates [temp.func.order].

The rule is that we synthesize a new type for each template type parameter and attempt to perform deduction on each other overload. For 1, we synthesize a type Unique1, which fails deduction on 2 because T is a non-deduced context. For 2, we synthesize a type Unique2, which succeeds deducing T = typename identity<Unique2>::type. Since deduction succeeds in one direction and not the other, that makes 2 more specialized than 1, hence it's preferred.

Note that template partial ordering rules are somewhat incomplete in the standard. If you simply add another argument of type T, the preference flips.