I am just wondering why the following code gives ambiguous overload error?
error: call of overloaded ‘fn(B)’ is ambiguous fn(B{});
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class B {
public:
int x;
};
void fn(B&& b) { //[x]
return;
}
void fn(B b) { //[y]
return;
}
int main() {
B b;
fn(B{}); //[1]
fn(b); //[2]
return 0;
}
a) Why does code works fine when we comment [1] ?
b) How does [2] get resolved but [1] gives error, shouldn't it be that if [1]
gives ambiguous overload error, [2] also should give ambiguous overload
error.
c) [1] passes a r-value then why [x] and [y] are ambiguous, isn't [x] a
perfect match for fn. call at [1], why is it not resolved.
I guess you are under the impression that [y] would only bind lvalues, but this is not the case. If you want to select between lvalues and rvalues, you would overload for (generally const) lvalue references and (generally non-const) rvalue references:
1 2 3 4 5 6 7 8 9
void fn(B&& b) { //[x]
// later: move from the lvalue b, bound to some rvalue:
// use(std::move(b));
}
void fn(B const &b) {//[y]
// later:
// use(b);
}
Probably you wouldn't be surprised by the ambiguity here:
1 2 3 4 5
int f(int &i); // [ a ]
int f(int i); // [ b ]
// ...
int i = 24;
f(i);
This is ambiguous because i can either be bound to the lvalue reference in [ a ] or copied to initialize the parameter in [ b ].
Similarly, given
1 2 3 4
int g(int &&i); // [ c ]
int g(int i); // [ d ]
// ...
g(24);
The prvalue 24 can either be bound to the rvalue reference parameter in [ c ] or used to construct the int in [ d ].