Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use std::forward to forward arguments?

C++0x shows an example of using std::forward:

template<class T> void foo(T&& arg)  {   bar(std::forward<T>(arg)); } 

When is it advantageous to use std::forward, always?

Also, it requires to use && in the parameters declaration, is it valid in all cases? I thought you had to pass temporaries to a function if the function was declared with && in it, so can foo be called with any parameter?

Lastly, if I have a function call such as this:

template<int val, typename... Params> void doSomething(Params... args) {   doSomethingElse<val, Params...>(args...); } 

Should I use this instead:

template<int val, typename... Params> void doSomething(Params&&... args) {   doSomethingElse<val, Params...>(std::forward<Params>(args)...); } 

Also, if use the parameters twice in the function, i.e. forwarding to two functions at the same time, is it wise to use std::forward? Won't std::forward convert the same thing to a temporary twice, moving the memory and make it invalid for a second use? Would the following code be ok:

template<int val, typename... Params> void doSomething(Params&&... args) {   doSomethingElse<val, Params...>(std::forward<Params>(args)...);   doSomethingWeird<val, Params...>(std::forward<Params>(args)...); } 

I'm a bit confused by std::forward, and I'd gladly use some clearing up.

like image 899
coyotte508 Avatar asked Aug 31 '11 12:08

coyotte508


People also ask

When should I use std forward?

We use std::forward to retrieve the original value category. If for the handler we provided an rvalue then insert will move from it. If for the handler we provided an lvalue then insert will copy it. There are a lot of rules that come into play for the initial deceivingly simple code.

What does std :: forward do?

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 the difference between std :: forward and std :: move?

std::move takes an object and casts it as an rvalue reference, which indicates that resources can be "stolen" from this object. std::forward has a single use-case: to cast a templated function parameter of type forwarding reference ( T&& ) to the value category ( lvalue or rvalue ) the caller used to pass it.

What is perfect forwarding in C++?

What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.


1 Answers

Use it like your first example:

template <typename T> void f(T && x) {   g(std::forward<T>(x)); }  template <typename ...Args> void f(Args && ...args) {   g(std::forward<Args>(args)...); } 

That's because of the reference collapsing rules: If T = U&, then T&& = U&, but if T = U&&, then T&& = U&&, so you always end up with the correct type inside the function body. Finally, you need forward to turn the lvalue-turned x (because it has a name now!) back into an rvalue reference if it was one initially.

You should not forward something more than once however, because that usually does not make sense: Forwarding means that you're potentially moving the argument all the way through to the final caller, and once it's moved it's gone, so you cannot then use it again (in the way you probably meant to).

like image 165
Kerrek SB Avatar answered Sep 17 '22 17:09

Kerrek SB