What does the single ampersand after the parameter list of a member function declaration mean?
It means the member will be invoked when the object is an lvalue reference.
[C++11: 9.3.1/5]:
A non-static member function may be declared with a ref-qualifier (8.3.5); see 13.3.1.
[C++11: 13.3.1/4]:
For non-static member functions, the type of the implicit object parameter is
- “lvalue reference to cv
X
” for functions declared without a ref-qualifier or with the&
ref-qualifier- “rvalue reference to cv
X
” for functions declared with the&&
ref-qualifierwhere
X
is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [..](and some more rules that I can't find)
Without a ref-qualifier, the function can always be invoked, regardless of the value category of the expression through which you're invoking it:
struct foo
{
void bar() {}
void bar1() & {}
void bar2() && {}
};
int main()
{
foo().bar(); // (always fine)
foo().bar1(); // doesn't compile because bar1() requires an lvalue
foo().bar2();
foo f;
f.bar(); // (always fine)
f.bar1();
f.bar2(); // doesn't compile because bar2() requires an rvalue
}
Live demo (thanks Praetorian)
But what does the single ampersand mean?
The function can only be called on an lvalue, not on an rvalue.
How is it different than without the ampersand?
Without a ref-qualifier you can invoke the function on an lvalue or an rvalue.
With a ref-qualifier you can only call the function on the corresponding value category.
A function without a ref-qualifier can be called for both rvalue and lvalues. A function with a &&
ref-qualifier can only be called for rvalues. A function with a &
ref-qualifier can only be called for lvalues.
class No { void foo(); };
class L { void foo() &; };
class R { void foo() &&; };
No().foo(); // valid
No no; no.foo(); // valid
L().foo(); // invalid
L l; l.foo(); // valid
R().foo(); // valid
R r; r.foo(); // invalid
Unfortunately, I can only find this rule in 5.5/6, which applies only to pointer-to-member dereference expressions. I know it applies otherwise too.
Furthermore, you cannot overload on ref-qualifier vs no ref-qualifier, see 13.1/2 bullet 3. You can overload on &
vs &&
.
(And due to my fruitless search of the standard, LRiO's answer now has all that info too.)