Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would you explicitly move a forwarding reference?

I'm looking at some code, and I see the following function:

template <typename... Args>
static return_t make_return(Args &&... args)
{
    // using std::forward<Args> will preserve lvalue args as such, but the point of this function
    // is to make a return, where the 99.9+% case is moving a local (lvalue) into the return pack.
    // Thus it forces a move, which will move `T&` args (but _not_ `const T&` args) into the
    // return pack so that users don't need to type out a bunch of std::moves themselves/
    // If they don't want implicit move they can just call std::make_tuple directly
    return std::make_tuple(std::move(args)...);
}

The documentation here confuses me.
Why would you explicitly move a forwarding reference?
Wouldn't you want to preserve the lvalue / rvalue within a generic context?
I'm having trouble understanding the rationale or how this behavior would be different from the recommended std::forward.

To put it another way,
I've never seen anyone explicitly opt-out from perfectly-forwarding a forwarding reference.
Does it make sense?

like image 956
Trevor Hickey Avatar asked Feb 06 '18 19:02

Trevor Hickey


People also ask

What are forwarding references?

I understand that a forwarding reference is "an rvalue reference to a cv-unqualified template parameter", such as in. template <class T> void foo(T&& ); which means the above function can take both l-value and r-value reference.

Why is perfect forwarding?

Perfect forwarding reduces excessive copying and simplifies code by reducing the need to write overloads to handle lvalues and rvalues separately.

What is the point of std :: forward?

std::forward has a single use case: to cast a templated function parameter (inside the function) to the value category (lvalue or rvalue) the caller used to pass it. This allows rvalue arguments to be passed on as rvalues, and lvalues to be passed on as lvalues, a scheme called “perfect forwarding.”

What is forwarding in C++?

Well, it means that a function template can pass its arguments through to another function whilst retaining the lvalue/rvalue nature of the function arguments by using std::forward.


1 Answers

Why would you explicitly move a forwarding reference?

Because it isn't being used for its forwarding properties. Yes, you are correct, we usually std::forward a forwarding reference. But in this case the author used forwarding references solely as a matter of convenience. If it was written as make_return(Args&... args) then it would be impossible to pass an rvalue to make_return, since a non-const lvalue reference may not bind to one.

By using forwarding references, the author allows passing values of any value category into the function, without incurring extra copies if none are needed. The documentation is there to clarify that the function signature isn't for forwarding, but simply for binding to whatever arguments it's given to move out.

like image 107
StoryTeller - Unslander Monica Avatar answered Oct 23 '22 00:10

StoryTeller - Unslander Monica