C++ Template Functions Overload Resolution

Overload resolution of template functions

the template argument deduction does not take the return type into account,

Yes. Template argument deduction is performed based on function arguments.

so why max<int> is ambiguous and not max<double>?

Given ::max<int>(7, 4.), for the 1st overload, the 1st template parameter T1 is specified as int, and T2 is deduced as double from the 2nd function argument 4., then the instantiation would be double max(int, double). For the 2nd overload, the 1st template parameter RT is specified as int, T1 is deduced as int from 7, T2 is deduced as double from 4., then the instantiation would be int max(int, double). Overload resolution doesn't consider return type too, the two overloads are both exact match and then ambiguous.

Given ::max<double>(7, 4.), for the 1st overload, the 1st template parameter T1 is specified as double, and T2 is deduced as double from 4., so the instantiation would be double max(double, double). For the 2nd overload, the 1st template parameter RT is specified as double, T1 is deduced as int from 7, T2 is deduced as double from 4., then the instantiation would be double max(int, double). Then the 2nd overload wins in overload resolution because it's an exact match, the 1st one requires the implicit conversion from int to double for the 1st argument 7.

overload resolution of template function with auto

As per [over.over]/2, we perform template argument deduction. This will succeed for all three overloads: in the first one, keep [temp.deduct.funcaddr]/2 in mind:

A placeholder type (7.1.7.4) in the return type of a function template is a non-deduced context. If template
argument deduction succeeds for such a function, the return type is determined from instantiation of the
function body.

Since the deduction will succeed (given that all template parameters have explicitly supplied arguments), the return type is deduced as int. In the second case, deduction succeeds since the argument is provided, and in the third, T will be deduced.

Going on to paragraph 4,

If more than one function is selected, [...] any given
function template specialization F1 is eliminated if the set contains
a second function template specialization whose function template is
more specialized than the function template of F1 according to the
partial ordering rules of 14.5.6.2. After such eliminations, if any, there shall remain exactly one selected function.

According to [temp.deduct.partial]/3, the function templates' function types are used for partial ordering. We can immediately see that #1 and #2's function types do not contain any template parameters that participate in deduction, hence via the addition to [temp.deduct.partial]/4 introduced by core issue 1391's resolution, their corresponding Ps are not used to determine the ordering. @bogdan explained here why that resolution is problematic; the bottom line is that ordering just yields an ambiguity for #1 and #2.

That is, according to current (probably defective) wording, the conversion is ill-formed in all cases. If partial ordering is fixed for pairs of non-dependent/deducing parameters,

  • case 1 and 3 are ambiguous, because for two non-dependent function types (the ones of #1 and #2), there is no ordering pair.
  • the accepting behavior in case 2 is correct (as expected).

[temp.deduct.type]/8 element 9 (T()), in case you were curious.

Overload resolution, order of defined functions and templates

When the compiler is parsing the first function (the template) it doesn't know anything about the second overload of func. Parsing is done top-to-bottom of the source file.

That's the reason you need to have declarations of symbols before you use them. That also means just having a declaration of bool func(int64_t); at the top would solve your problem.

Overloading Function templates Rules

For the 1st overload, if T1 is specified as long double, and pass 7.2 which is a double, the implicit conversion from double to long double is required. For the 2nd overload, RT is specified as long double, and T1 will be deduced as double, so it's an exact match and wins in overload resolution.

If you specify template argument as double as ::max<double>(7.2, 4);, both of them are exact match and the call will be ambiguous.

Template overload resolution: what happens when multiple templates match?

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.



Related Topics



Leave a reply



Submit