Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overload resolution of template functions

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 ?

like image 210
DamissaK Avatar asked Sep 04 '19 13:09

DamissaK


Video Answer


1 Answers

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.

like image 106
songyuanyao Avatar answered Sep 28 '22 15:09

songyuanyao