Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);    
}
like image 706
Igor R. Avatar asked Sep 04 '16 18:09

Igor R.


1 Answers

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.

like image 193
Barry Avatar answered Oct 19 '22 01:10

Barry