c++templates

Function template overlading with multiple matches


I have two template max functions and try to call one of them.

    #include <iostream>
    #include <type_traits>
    
    template <typename T1, typename T2>
    auto max(T1 a, T2 b) {
        return b < a ? a : b;
    }
    
    template <typename RT, typename T1, typename T2>
    RT max(T1 a, T2 b) {
        return b < a ? a : b;
    }
    
    int main(void) {
        max<int>(4, 7.2);
        return 0;
    }

Here, max<int>(4, 7.2) causes ambiguity, generating the compilation error.

<source>: In function 'int main()':
<source>:15:13: error: call of overloaded 'max<int>(int, double)' is ambiguous
   15 |     max<int>(4, 7.2);
      |     ~~~~~~~~^~~~~~~~
<source>:5:6: note: candidate: 'auto max(T1, T2) [with T1 = int; T2 = double]'
    5 | auto max(T1 a, T2 b) {
      |      ^~~
<source>:10:4: note: candidate: 'RT max(T1, T2) [with RT = int; T1 = int; T2 = double]'
   10 | RT max(T1 a, T2 b) {
      |    ^~~
Compiler returned: 1

Two max functions can be interpreted as follows when calling max<int>(4, 7.2):

double max(int a, double b) {
   return b < static_cast<double>(a) ? static_cast<double>(a) : b;
}

int max(int a, double b) {
   return b < static_cast<double>(a) ? static_cast<double>(a) : b;
}

A compiler might prefer the first one because it has a higher precision when returning value.

Why does ambiguity happen in this case?


Solution

  • The return type is not consider in function overloading since it can result in ambiguity of which function to call. For example:

    int foo();
    double foo();
    
    int x = foo(); // Which one should be called?