Question:
class A
{
public:
void f() &;
};
What does & mean after a function declaration?
Answer:
This means that the function can be called on the 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
function f
overloaded for lvale
objects of class A
and for rvalue
objects of class A
In this program in the sentence
a.f();
function f
is called on the lvalue
object a
.
In the same sentence
A().f();
the 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 constant lvalue
objects and the other for non-constant lvalue
objects.
In a sentence
a.f();
the function is called for non-const objects, since object a
not const.
However, inside the function h
h( a );
the overloaded function for constant objects is called because the function parameter is a constant reference.
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 rvalue
cannot be bound to a non-const reference.
However, if you declare a function as dealing 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, you can represent these functions as follows.
Each non-static member function of the class has an implicit parameter that corresponds to 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 for temporary objects of type A *
, while the first one can be, since a constant reference can bind to a temporary object.
Here is an example that demonstrates the above in a simplified way.
#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 & )