#include <iostream>
struct A
{
void f() const &
{
std::cout << "A::f()&" << std::endl;
}
void f() const &&
{
std::cout << "A::f()&&" << std::endl;
}
};
struct B
{
void f() const &
{
std::cout << "B::f()&" << std::endl;
}
};
int main()
{
A{}.f();
B{}.f();
}
The output is:
A::f()&&
B::f()&
Note that void B::f() const &&
doesn't exist.
To me, a temporary object of B
calls B::f
, void B::f() const &&
should be chosen, or a compiler error should be raised.
Why is void B::f() const &
chosen in such a case?
Because void B::f() const &&
doesn't exist, the next best candidate is selected which is your void B::f() const &
. The rvalue will bind to a const &
. If you remove the const you will notice you will get a compile error as the rvalue cannot bind to a non-const reference. The example on cppreference/overloadresolution shows it perfectly.
int i;
int f1();
int g(const int&); // overload #1
int g(const int&&); // overload #2
int j = g(i); // lvalue int -> const int& is the only valid conversion
int k = g(f1()); // rvalue int -> const int&& better than rvalue int -> const int&
This is no different for the implicit this
argument in your examples.
To me, a temporary object of B calls B::f, void B::f() const && should be chosen, or a compiler error should be raised.
if this was the case then code like the following would break without a [const] rvalue reference overload existing.
void f(const int& i)
{
std::cout << i;
}
int main()
{
f(3);
}