In your example, the T&&
is wrong, it's a dangling reference.
But std::forward
doesn't return an rvalue reference to a local variable in its own definition, it returns an rvalue reference to its by-rvalue-reference argument (or an lvalue reference to a by-lvalue-reference argument).
You should return an rvalue reference only if you want the caller of your function to be able to move from whatever that reference refers to.
Normally that will only be if the purpose of the function is to provide move access to some significant object (perhaps which already exists). So that includes std::move
(which allows you to move from an lvalue), and similarly you might write an accessor function specifically designed for users to move from a data member of some object, or an element of some container. If the object itself isn't significant, only the value, then you can return by value.
As grizzly says, sometimes due to reference collapsing you can take advantage of tricks which mean that you type T&&
in your code, but when T
is already an lvalue-reference type T&&
is the same lvalue reference type. std::forward
uses that trick. That is to say, because of reference collapsing T&&
doesn't mean "rvalue reference to T", it means "T if T is a reference type, otherwise rvalue reference to T".