Came across a proposal called \"rvalue reference for *this\" in clang\'s C++11 status page.
I\'ve read quite a bit about rvalue references and understood them, but I
Let's say you have two functions on a class, both with the same name and signature. But one of them is declared const
:
void SomeFunc() const;
void SomeFunc();
If a class instance is not const
, overload resolution will preferentially select the non-const version. If the instance is const
, the user can only call the const
version. And the this
pointer is a const
pointer, so the instance cannot be changed.
What "r-value reference for this` does is allow you to add another alternative:
void RValueFunc() &&;
This allows you to have a function that can only be called if the user calls it through a proper r-value. So if this is in the type Object
:
Object foo;
foo.RValueFunc(); //error: no `RValueFunc` version exists that takes `this` as l-value.
Object().RValueFunc(); //calls the non-const, && version.
This way, you can specialize behavior based on whether the object is being accessed via an r-value or not.
Note that you are not allowed to overload between the r-value reference versions and the non-reference versions. That is, if you have a member function name, all of its versions either use the l/r-value qualifiers on this
, or none of them do. You can't do this:
void SomeFunc();
void SomeFunc() &&;
You must do this:
void SomeFunc() &;
void SomeFunc() &&;
Note that this declaration changes the type of *this
. This means that the &&
versions all access members as r-value references. So it becomes possible to easily move from within the object. The example given in the first version of the proposal is (note: the following may not be correct with the final version of C++11; it's straight from the initial "r-value from this" proposal):
class X {
std::vector data_;
public:
// ...
std::vector const & data() const & { return data_; }
std::vector && data() && { return data_; }
};
X f();
// ...
X x;
std::vector a = x.data(); // copy
std::vector b = f().data(); // move