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 notmax<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 specializationF1
is eliminated if the set contains
a second function template specialization whose function template is
more specialized than the function template ofF1
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 P
s 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
specializationtemplate<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
What Is a Constant Reference? (Not a Reference to a Constant)
Differentiate Between Function Overloading and Function Overriding
Function Returning a Lambda Expression
Windows C++ Compiler with Full C++11 Support (Should Work with Qt)
Error Lnk2005: Xxx Already Defined in Msvcrt.Lib(Msvcr100.Dll) C:\Something\Libcmt.Lib(Setlocal.Obj)
Garbage Collection in C++ -- Why
Video Stabilization with Opencv
Detect Windows or Linux in C, C++
Windows/C++: How to Find the Line of Code Where Exception Was Thrown Having "Exception Offset"
What Is a Scalar Object in C++
Is There Any Standard Way of Embedding Resources into Linux Executable Image
Boost_Static_Assert Without Boost
Detecting Usb Insertion/Removal Events in Windows Using C++
With a Private Modifier, Why Can the Member in Other Objects Be Accessed Directly