C++11 std::forward_as_tuple and std::forward
You must use std::forward
in order to preserve the value category of the argument(s) to fn()
. Since the arguments have a name within fn
, they are lvalues, and without std::forward
they will always be passed as such to std::forward_as_tuple
.
The difference can be demonstrated using the following example:
template<typename T>
void bar2(T&& t)
{
std::cout << __PRETTY_FUNCTION__ << ' '
<< std::is_rvalue_reference<decltype(t)>::value << '\n';
}
template<typename T>
void bar1(T&& t)
{
std::cout << __PRETTY_FUNCTION__ << ' '
<< std::is_rvalue_reference<decltype(t)>::value << '\n';
bar2(std::forward<T>(t));
bar2(t);
}
bar1
always passes it arguments on to bar2
, once with std::forward
and once without. Now let's call them with an lvalue and an rvalue argument.
foo f;
bar1(f);
std::cout << "--------\n";
bar1(foo{});
Output:
void bar1(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
void bar2(T&&) [with T = foo&] 0
--------
void bar1(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo] 1
void bar2(T&&) [with T = foo&] 0
As you can see from the output, in both cases, without the use of std::forward
, the argument is being passed as an lvalue to bar2
.
Yes, you almost certainly do want to use std::forward
here, this is assuming that the arguments in list
are not used after the called to call_fn
. This is a typical use case of std::forward
, in that you want to exercise the semantics of perfect forwarding.
std::forward
preserves the value category of its arguments (i.e. lvalues as lvalues, rvalues as rvalues). std::forward_as_tuple
in turn will do the same, as if std::tuple<List&&...>(std::forward<List>(list)...)
had been called.
A note on the "stored as rvalue references". It is not that the arguments List
in the parameter pack are all rvalues references (they could be), but the List
is being deduced in this context, hence reference collapsing will apply and the deduced type(s) could be rvalue references or lvalue references. During the creation of the std::tuple
, it is this distinction that you would want to maintain/preserve.