Does a return type like this represent something meaningful in c++11?
template <typename R>
R&& grabStuff();
T instance = grabStuff<T>();
I would hope that grabStuff
should throw a compile-time error if R
does not have a move constructor, since this would seem to disallow the return type to use a copy constructor
Rvalue references enable you to write one version of a function that accepts arbitrary arguments. Then that function can forward them to another function as if the other function had been called directly. Consider the following example that declares four types, W , X , Y , and Z .
“l-value” refers to a memory location that identifies an object. “r-value” refers to the data value that is stored at some address in memory. References in C++ are nothing but the alternative to the already existing variable. They are declared using the '&' before the name of the variable.
An rvalue reference is formed by placing an && after some type. An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue.
Move semantics is a set of semantic rules and tools of the C++ language. It was designed to move objects, whose lifetime expires, instead of copying them. The data is transferred from one object to another. In most cases, the data transfer does not move this data physically in memory.
As always, when returning references you must return a reference to something that's still alive after the function returns. How you do that is up to you. Example:
T global_thing;
T && get() { return std::move(global_thing); }
struct Foo { Foo(T &&); /* ... */ };
int main()
{
global_thing.reset();
Foo a(get());
global_thing.reset();
Foo b(get());
}
The more typical example for returning an rvalue reference is std::move
itself, though, which returns a reference to the thing you pass into it (and thus it's the caller's responsibility to provide a valid input).
If the return type of a function is an rvalue reference, then the result of the function call is an xvalue; if the return type is non-reference, then the result of the function call is a prvalue.
Both xvalue and prvalue are rvalues, there are some minor differences between them, more like differences between reference and non-reference. For example, an xvalue may have an incomplete type, while a prvalue shall usually have a complete type or the void type. When typeid is applied to an xvalue whose type is a polymorphic class type, the result refers to the dynamic type; and for prvalue, the result refers to the static type.
For your declaration statement T instance = grabStuff<T>();
, if T is a class type, I think there is no difference between xvalue and prvalue in this context.
The initializer is an rvalue, so the compiler prefers a move constructor. But if no move constructor is declared, and a copy constructor with const reference parameter is declared, then this copy constructor will be chosen, and there is no error. I don't know why do you want this to be an error. If this is an error, any old code will be incorrect when copy-initialize some object from an rvalue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With