Search code examples
c++overload-resolution

Priority confusion on function overloading with multiple parameters


I'm learning C++ at school. We are currently on the topic of overloading functions. We were given an exercice with a intial code block. Then, we are shown a function call, we have to determine which function is choosen, or if the call is ambiguous (if it is). We use C++20.

This is the code block,

void fct (      int,          float)  {cout << "Function no 1" << endl;}
void fct (      int,          double) {cout << "Function no 2" << endl;}
void fct (      float&,       int&)   {cout << "Function no 3" << endl;}
void fct (const float&, const int&)   {cout << "Function no 4" << endl;}

      int       i = 1;
      int&     ri = i;
      char      c = 'A';
      float     f = 2.f;
      double    d = 3.0;
const double& rdC = d;

There are two functions calls that give me problems.

Call A: fct(f, 1);

For call A, our logic was :

  • for the first parameter (f), function 3 and 4 are both callable and share the same level of priority (which is perfect type correspondence).
  • for the second parameter (1), function 1, 2, 4 are callable, but function 4 has the highest priority level (which is perfect type correspondence).

Since function 4 is callable for both parameters, our conclusion is that function 4 is called, and it turns out that this what happens. Yay!

Call B: fct(f, i);

For call B, our logic was :

  • for the first parameter (f), function 3 and 4 are both callable and share the same level of priority (which is perfect type correspondence).
  • for the second parameter (i), function 3 and 4 are both callable and share the same level of priority (which is perfect type correspondence). So same thing for both parameters.

Since two functions are callable and share the same priority level for both parameters, we conclude that the call is ambiguous. BUT, it turns out that it's not, and that function 3 is called. And this, we do not understand.

We then assumed that for parameter (f), float& has highest priority than const float&, but then call A should be ambiguous (and it's not).

tl; dr

  • for call A, we expect no4, and it is no4,
  • for call B, we expect ambiguous, but it's no3.

Why?


Solution

  • Firstly, note that two things can make a difference in overload resolution:

    fct(f, 1)

    • f is a float, so none of the candidates are disqualified. Either reference binding or implicit conversions make the call possible. Candidate no 3. and 4. are better than no 1. and no 2.
    • 1 is an rvalue of type int, and const int& but not int& can bind to it. Reference binding makes for a better conversion sequence than conversion to float or double.

    Therefore, no. 4 is the best candidate.

    fct(f, i)

    • for f, see the explanation above.
    • i is an lvalue of type int, and binding an int& to it is better than binding a const int& because the addition of const is an extra qualification conversion. Furthermore, reference binding is better than converting int to float or double.

    Therefore, no. 3 is the best candidate.