I've seen one very motivating use case for rvalue reference data members, and it is in the C++0x draft:
template<class... Types>
tuple<Types&&...>
forward_as_tuple(Types&&... t) noexcept;
Effects: Constructs a tuple of
references to the arguments in t
suitable for forwarding as arguments
to a function. Because the result may
contain references to temporary
variables, a program shall ensure that
the return value of this function does
not outlive any of its arguments.
(e.g., the program should typically
not store the result in a named
variable).
Returns: tuple<Types&&...>(std::forward<Types>(t)...)
The tuple has rvalue reference data members when rvalues are used as arguments to forward_as_tuple, and otherwise has lvalue reference data members.
I've found forward_as_tuple subsequently helpful when needing to catch variadic arguments, perfectly forward them packed as a tuple, and re-expand them later at the point of forwarding to a functor. I used forward_as_tuple in this style when implementing an enhanced version of tuple_cat proposed in LWG 1385:
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1385
You seem to be confused as to what an rvalue reference is and how it relates to move semantics.
First thing's first: &&
does not mean move. It is nothing more than a special reference type. It is still a reference. It is not a value; it is not a moved value; it is a reference to a value. Which means it has all of the limitations of a reference type. Notably, it must refer to a value that still exists. So returning a dangling r-value reference is no better than returning a dangling l-value reference.
"Moving" is the process of having one object claim ownership of the contents of another object. R-value references facilitate move semantics, but simply having a &&
does not mean anything has moved. Movement only happens when a move constructor (or move assignment operator) is called; unless one of those two things is called, no movement has occurred.
If you wish to move the contents of a std::vector
out of your function to the user, you simply do this:
std::vector<int> fill_list() {
std::vector<int> res;
... do something to fill res ...
return res;
}
Given this usage of fill_list()
:
std::vector<int> myvec = fill_list();
One of two things will happen. Either the return will be elided, which means that no copying or moving happens. res
is constructed directly into myvec
. Or res
will be moved into the return value, which will then perform move-initialization of myvec
. So again, no copying.
If you had this:
std::vector<int> myvec;
myvec = fill_list();
Then again, it would be moved into. No copying.
C++11 knows when it's safe to implicitly move things. Returning a value by value rather than by reference or something is always a safe time to move. Therefore, it will move.
Best Answer
I hate to be circular, but an rvalue reference to function type is an rvalue reference to function type. There is such a thing as a function type, e.g.
void ()
. And you can form an rvalue reference to it.In terms of the classification system introduced by N3055, it is an xvalue.
Its uses are rare and obscure, but it is not useless. Consider for example:
x
has type:And if you look at the synopsis for
reference_wrapper
it includes:In this example
T
is the function typevoid ()
. And so the second declaration forms an rvalue reference to function type for the purpose of ensuring thatreference_wrapper
can't be constructed with an rvalue argument. Not even ifT
is const.If it were not legal to form an rvalue reference to function, then this protection would result in a compile time error even if we did not pass an rvalue
T
to the constructor.