ppm
ppm

Reputation: 178

Template overload resolution: what happens when multiple templates match?

The following program prints T,T.

#include <iostream>

template<typename T>
void f(T x, T y) {
  std::cout << "T,T\n";
}

template<typename T1, typename T2> 
void f(T1 x, T2 y) {
  std::cout << "T1,T2\n";
}

int main() {
  f(1, 1); 
  return 0;
}

It makes no difference which template comes first in the code.

I would expect overload resolution to be ambiguous here. T, T1, and T2 should all be deduced as int, which makes both templates match the call site exactly.

I haven't been able to find any resolution rules (https://en.cppreference.com/w/cpp/language/overload_resolution) to explain why it would choose the first template.

I tested with clang++ -std=c++17, in case that matters.

Upvotes: 7

Views: 1391

Answers (2)

Sergey Aleksandrovich
Sergey Aleksandrovich

Reputation: 236

Maybe a part of answer is here Implicit_instantiation

When code refers to a function in context that requires the function definition to exist, and this particular function has not been explicitly instantiated, implicit instantiation occurs. The list of template arguments does not have to be supplied if it can be deduced from context

The compiler connects call f(1, 1) with instantiation f<int>. When the first template (template<typename T> void f(T x, T y)) is removed in the code, the compiler connects call f(1, 1) with instantiation f<int, int>. You can call each instantiation using explicit indication of types:

f(1, 1);
f<int>(1, 1);
f<int, int>(1, 1);

output is:

T,T
T,T
T1,T2

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172924

Partial ordering of overloaded function templates is performed to determine which one should be selected.

When the same function template specialization matches more than one overloaded function template (this often results from template argument deduction), partial ordering of overloaded function templates is performed to select the best match.

Specifically, partial ordering takes place in the following situations:

1) overload resolution for a call to a function template specialization

template<class X> void f(X a);
template<class X> void f(X* a);
int* p;
f(p);

2) ...

...

Informally "A is more specialized than B" means "A accepts fewer types than B".

The 1st overload is selected because it only accepts arguments with one same type, while the 2nd one could accept arguments with two independent types.

Upvotes: 7

Related Questions