Question:
class A
{
public:
void f() &;
};
What does & mean after a function declaration?
Answer:
This means that the function can be called on an lvalue
object of class A
.
Consider the following example
#include <iostream>
class A
{
public:
void f() & { std::cout << "A::f() &" << std::endl; }
void f() && { std::cout << "A::f() &&" << std::endl; }
};
int main()
{
A a;
a.f();
A().f();
}
Console output of this program
A::f() &
A::f() &&
In class A
, the function f
is overloaded for lvale
objects of class A
and for rvalue
objects of class A
.
In this program, the offer
a.f();
the function f
is called on the lvalue
object a
.
In the same proposal
A().f();
function f
is called on the rvalue
object A()
.
Another example.
#include <iostream>
class A
{
public:
void f() const & { std::cout << "A::f() const &" << std::endl; }
void f() & { std::cout << "A::f() &" << std::endl; }
};
void h( const A &a )
{
a.f();
}
int main()
{
A a;
a.f();
h( a );
}
Console output
A::f() &
A::f() const &
In this example, class A declares two overloaded functions named f
: one for const lvalue
objects and one for non-const lvalue
objects.
In a sentence
a.f();
the function is called for non-const objects, since object a
is not const.
However, inside the function h
h( a );
the overloaded function is called for const objects because the function parameter is a reference constant.
One more example.
This program will not compile
#include <iostream>
class A
{
public:
void f() & { std::cout << "A::f() &" << std::endl; }
};
int main()
{
A().f();
}
Because an rvalue
cannot be bound to a non-const reference.
However, if you declare a function to deal with a constant reference, then the program will compile
#include <iostream>
class A
{
public:
void f() const & { std::cout << "A::f() const &" << std::endl; }
};
int main()
{
A().f();
}
To make it clearer, we can represent these functions as follows.
Every non-static class member function has an implicit parameter that matches this
Therefore, these two member functions of the class
void f() const &
and
void f() &
conceptually look like
void f( A * const & ) /*const &*/
and
void f( A * & ) /*&*/
Therefore, the last function cannot be called on temporary objects of type A *
, while the first one can, since a constant reference can bind to a temporary object.
Here is an example that simply demonstrates what has been said
#include <iostream>
void f( int * const & ) { std::cout << "f( int * const & ) " << std::endl; }
void f( int * & ) { std::cout << "f( int * & )" << std::endl; }
int main()
{
int i = 10;
int *pi = &i;
f( pi );
f( &i );
}
Console output:
f( int * & )
f( int * const & )