This question already has answers here:
What does the single ampersand after the parameter list of a member function declaration mean?
(3 answers)
Closed 8 years ago.
I have seen in an anwser there:
Is returning by rvalue reference more efficient?
The member function definition:
Beta_ab const& getAB() const& { return ab; }
I am familiar with the cv-qualifier (const) on member functions, but not const&.
What does the last const& mean?
The & is a ref-qualifier. Ref-qualifiers are new in C++11 and not yet supported in all compilers, so you don't see them that often currently. It specifies that this function can only be called on lvalues (and not on rvalues):
#include <iostream>
class kitten
{
private:
int mood = 0;
public:
void pet() &
{
mood += 1;
}
};
int main()
{
kitten cat{};
cat.pet(); // ok
kitten{}.pet(); // not ok: cannot pet a temporary kitten
}
Combined with the cv-qualifier const, it means that you can only call this member function on lvalues, and those may be const.
We know that in this code...
Beta_ab const& getAB() const { return ab; }
^^^^^
The highlighted const means that the member function may be called upon a const object. A member function can always be called upon a non-const object regardless of the function's cv-qualification.
So in this code...
Beta_ab const& getAB() const & { return ab; }
^
We should expect that the highlighted & also says something about what kinds of objects this member function is allowed to be called upon. We would be correct; in C++11, this says that the member function may only be called upon lvalues.
Beta_ab const& getAB() const& { return ab; }
Beta_ab && getAB() && { return ab; }
In the above example, the first overload is invoked on lvalues, and the second overload is invoked on non-const rvalues. Similar to the following more familiar example, with qualifiers applied to ordinary function parameters:
void setAB(AB const& _ab) { ab = _ab; }
void setAB(AB && _ab) { ab = std::move(_ab); }
It works slightly differently for ordinary parameters though, as in this example, the first overload would accept an rvalue if the second overload were removed.
Related
This question already has an answer here:
How does const modifier for member functions affect overload resolution?
(1 answer)
Closed 2 years ago.
I see the below code today.
I know the difference between returning a reference and returning a const reference.
But I don't know when T& operator()* will be called, and when const T& operator()const* will be called.
They have the same name.
template<typename T>
class CSmartPtr
{
public:
CSmartPtr(T *ptr = nullptr) :mptr(ptr) {}
~CSmartPtr() { delete mptr; }
T& operator*() { return *mptr; }
const T& operator*()const { return *mptr; }
private:
T *mptr;
};
int main()
{
CSmartPtr<int> ptr(new int);
*ptr = 20;
cout << *ptr << endl;
return 0;
}
But I don't know when T& operator()* will be called, and when const T& operator()const* will be called.
They have the same name.
In this case, if the member function is called on a const object, the const method will be invoked, and the non-const method will be invoked for a non-const object.
How does caller know which member functions of same name shall be called?
They don't know that, and they shouldn't know that either. The whole point of overload sets is that the caller doesn't know which exact overload is called. That is intended to be an implementation detail. The caller should use the same syntax when they call a function from an overload set.
It's up to the author of the overload set that the right thing is done depending on the arguments that the function is called with.
If you do want the caller to know which function is called, then don't use an overload set at all, just provide functions with different names.
Recently I was reading through the API of boost::optional and came across the lines:
T const& operator *() const& ;
T& operator *() & ;
T&& operator *() && ;
I also wrote my own program that defines member functions as const&, & and && (Note that I am not speaking about the return type, but the specifiers just before the semi-colons) and they seems to work fine.
I know what it means to declare a member function const, but can anyone explain what it means to declare it const&, & and &&.
const& means, that this overload will be used only for const, non-const and lvalue object.
const A a = A();
*a;
& means, that this overload will be used only for non-const object.
A a;
*a;
&& means, that this overload will be used only for rvalue object.
*A();
for more information about this feature of C++11 standard you can read this post What is "rvalue reference for *this"?
It is a member function ref-qualifiers; it is one of the features added in C++11. It is possible to overload non-static member functions based on whether the implicit this object parameter is an lvalue or an rvalue by specifying a function ref-qualifier (some details).
To specify a ref-qualifier for a non-static member function, you can either qualify the function with & or &&.
#include <iostream>
struct myStruct {
void func() & { std::cout << "lvalue\n"; }
void func() &&{ std::cout << "rvalue\n"; }
};
int main(){
myStruct s;
s.func(); // prints "lvalue"
std::move(s).func(); // prints "rvalue"
myStruct().func(); // prints "rvalue"
}
This question already has answers here:
What is "rvalue reference for *this"?
(3 answers)
Closed 4 years ago.
By mistake, I had a & at the end of a prototype (see example below). Neither gcc nor Clang complains about it. I noticed that the symbol generated is not exactly the same.
Example:
class A
{
public:
void fn() &
{
return;
}
};
int main()
{
A a;
a.fn();
return 1;
}
Name of the symbol without &: _ZN1A2fnEv and with &: _ZNR1A2fnEv.
What does it mean ? Do I miss something ?
Thanks,
The & at the end of the member function declaration is a ref qualifier. It applies to the object value on which the member function is called, and constrains that value's value category:
Functions without ref qualifiers can be called on any value.
Functions with & qualifier can only be called on lvalues.
Functions with && qualifier can only be called on rvalues.
The ref qualifier affects overload resolution, e.g. an overload on a mismatched instance value is not viable.
The standard library doesn't use ref qualifiers much (I can only think of std::optional), so let's make up our own example:
struct X {
explicit X(int n) : s_(n, 'a') {}
std::string s_;
const char* f1() const { return s_.c_str(); }
const char* f2() const & { return s_.c_str(); }
const char* f3() const && { return s_.c_str(); }
};
Now consider the following calls:
int main() {
X x(10);
x.f1(); // OK
X(20).f1(); // OK
x.f2(); // OK
X(20).f2(); // ill-formed
x.f3(); // ill-formed
X(20).f3(); // OK
}
The example also demonstrates why this feature may be useful: When a member function returns a reference to some internal part of the object itself, then it is important that that internal reference does not outlast the lifetime of the object. If your member function is unqualified, then you can very easily introduce lifetime bugs. For example:
const char* s = std::string("abcde").c_str(); // dangling pointer!
One way to improve such "internal state access" APIs is to create different return value (categories) for different ref-qualified overloads. To get back to std::optional, the engaged-access essentially boils down to this set of overloads:
struct MyOptional {
T value_; // assume engaged!
T& get() & { return value_; }
T&& get() && { return std::move(value_); }
};
That means that MyOptional::get returns an lvalue when invoked on an lvalue optional, and an rvalue (in fact an xvalue) when invoked on an rvalue. This means that, given MyOptional x;, the binding T& r = x.get(); is allowed, but T& r = MyOptional().get(); is not, and similarly T&& r = x.get(); is disallowed, but T&& r = std::move(x).get() is allowed.
Recently I was reading through the API of boost::optional and came across the lines:
T const& operator *() const& ;
T& operator *() & ;
T&& operator *() && ;
I also wrote my own program that defines member functions as const&, & and && (Note that I am not speaking about the return type, but the specifiers just before the semi-colons) and they seems to work fine.
I know what it means to declare a member function const, but can anyone explain what it means to declare it const&, & and &&.
const& means that this overload will be used only for const, non-const and lvalue objects, such as:
const A a = A();
*a;
& means that this overload will be used only for non-const objects:
A a;
*a;
&& means that this overload will be used only for rvalue objects:
*A();
For more information about this feature of the C++11 standard you can read this post: What is "rvalue reference for *this"?
It is a member function ref-qualifiers; it is one of the features added in C++11. It is possible to overload non-static member functions based on whether the implicit this object parameter is an lvalue or an rvalue by specifying a function ref-qualifier (some details).
To specify a ref-qualifier for a non-static member function, you can either qualify the function with & or &&.
#include <iostream>
struct myStruct {
void func() & { std::cout << "lvalue\n"; }
void func() &&{ std::cout << "rvalue\n"; }
};
int main(){
myStruct s;
s.func(); // prints "lvalue"
std::move(s).func(); // prints "rvalue"
myStruct().func(); // prints "rvalue"
}
Recently I was reading through the API of boost::optional and came across the lines:
T const& operator *() const& ;
T& operator *() & ;
T&& operator *() && ;
I also wrote my own program that defines member functions as const&, & and && (Note that I am not speaking about the return type, but the specifiers just before the semi-colons) and they seems to work fine.
I know what it means to declare a member function const, but can anyone explain what it means to declare it const&, & and &&.
const& means that this overload will be used only for const, non-const and lvalue objects, such as:
const A a = A();
*a;
& means that this overload will be used only for non-const objects:
A a;
*a;
&& means that this overload will be used only for rvalue objects:
*A();
For more information about this feature of the C++11 standard you can read this post: What is "rvalue reference for *this"?
It is a member function ref-qualifiers; it is one of the features added in C++11. It is possible to overload non-static member functions based on whether the implicit this object parameter is an lvalue or an rvalue by specifying a function ref-qualifier (some details).
To specify a ref-qualifier for a non-static member function, you can either qualify the function with & or &&.
#include <iostream>
struct myStruct {
void func() & { std::cout << "lvalue\n"; }
void func() &&{ std::cout << "rvalue\n"; }
};
int main(){
myStruct s;
s.func(); // prints "lvalue"
std::move(s).func(); // prints "rvalue"
myStruct().func(); // prints "rvalue"
}