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.
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.
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.”
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. 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.
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).
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