Consider this code:
#include <iostream>
//Number1
template<typename T1, typename T2>
auto max (T1 a, T2 b)
{
std::cout << "auto max(T1 a, T2 b)" <<std::endl;
return b < a ? a : b;
}
//Number2
template<typename RT, typename T1, typename T2>
RT max (T1 a, T2 b)
{
std::cout << "RT max(T1 a, T2 b)" << std::endl;
return b < a ? a : b;
}
int main()
{
auto a = ::max(4, 7.2); //Select Number1
auto b = ::max<double>(4, 7.4); //Select Number2
auto c = ::max<int>(7, 4.); //Compile-time error overload ambiguous
auto c = ::max<double>(7, 4.); //Select Number2
}
auto c = ::max<int>(7, 4.);
: This line fails to compile because of overload ambiguity with the following message:
maxdefault4.cpp:9:27: error: call of overloaded 'max(int, double)' is ambiguous
auto c = ::max<int>(7, 4.);
^
maxdefault4.cpp:9:27: note: candidates are:
In file included from maxdefault4.cpp:1:0:
maxdefault4.hpp:4:6: note: auto max(T1, T2) [with T1 = int; T2 = double]
auto max (T1 a, T2 b)
^
maxdefault4.hpp:11:4: note: RT max(T1, T2) [with RT = int; T1 = int; T2 = double]
RT max (T1 a, T2 b)
^
while the following code:
àuto c = ::max<double>(7, 4.)
succeed, why don't we have the same error message saying the call is amgiguous for max<double>
the same the way max<int>
failed ?
Why for double
there's no problem ?
I've read in "C++ templates, the completes Guide" book that the template argument deduction does not take the return type into account, so why max<int>
is ambiguous and not max<double>
?
Does the return type of a template function really not taken into account in argument dedcution ?
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With