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 isno4, - for call B, we expect ambiguous, but it's
no3.
Why?
Firstly, note that two things can make a difference in overload resolution:
fct(f, 1)fis afloat, 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.1is an rvalue of typeint, andconst int&but notint&can bind to it. Reference binding makes for a better conversion sequence than conversion tofloatordouble.Therefore, no. 4 is the best candidate.
fct(f, i)f, see the explanation above.iis an lvalue of typeint, and binding anint&to it is better than binding aconst int&because the addition ofconstis an extra qualification conversion. Furthermore, reference binding is better than convertinginttofloatordouble.Therefore, no. 3 is the best candidate.