Is there a difference between l-value ref-qualified member functions and unqualified member functions? If so, what is it?
I.e., are these two ways of declaring func()
different?
class Foo
{
void func();
void func() &;
};
I don't mean "are they different enough to permit overload resolution," because obviously the above class does not compile when both versions of func()
are present. I mean, how and why does the compiler behave differently when &
is included versus when it isn't?
There is at least one difference, which is that ref-qualified functions (of either l-value or r-value type) cannot be overloaded with non-ref-qualified functions. From the current standard draft:
Member function declarations with the same name and the same parameter-type-list as well as member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them, but not all, have a ref-qualifier.
...but if this is the only difference, why the restriction? I.e., why can't foo()&&
be treated as a valid override of (unqualified) foo()
?
They are different.
Foo foo;
std::move(foo).func();
will call func()
but not func()&
.
Similarly:
Foo make_foo() { return {}; }
make_foo().func();
will only work on the void func()
signature, not the void func()&
signature.
void func()&
means that it only is a valid call on lvalues, not rvalues.