How do I implement a function (foo) which passes a parameter pack to a function (bar) which finally passes that paramer pack to a class constructor? This is the code:
template <typename... Args>
void bar(Args&&... args)
{
MyObj obj(std::forward<Args>(args)...);
/* Do something with obj */
}
Do I have to implement foo as
template <typename... Args>
void foo(Args&&... args)
{ bar(args...); }
Or
template <typename... Args>
void foo(Args&&... args)
{ bar(std::forward<Args>(args)...); }
You need to use forward
. forward
looks like this:
template <class T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
(There is another overload of forward
, but it is irrelevant here.)
For each element Arg
of the template parameter pack Args
, Arg
can be either: (T
is a non-reference type)
T&
if the argument is a non-const lvalue, so that the parameter is of type T&
; or
const T&
if the argument is a const lvalue, so that the parameter is of type const T&
; or
T
if the argument is an rvalue, so that the parameter is of type T&&
.
In the first case, forward<Arg>(arg)
instantiates to:
constexpr T& forward(T& t) noexcept
{
return static_cast<T&>(t);
}
resulting in a non-const lvalue to be passed.
In the second case, forward<Arg>(arg)
instantiates to:
constexpr const T& forward(const T& t) noexcept
{
return static_cast<const T&>(t);
}
resulting in a const lvalue to be passed.
In the last case, forward<Arg>(arg)
instantiates to:
constexpr T&& forward(T&& t) noexcept
{
return static_cast<T&&>(t);
}
resulting in an rvalue to be passed.
In all three cases, the value category is preserved, and the value is forwarded with modification to bar
.
If you don't use forward
, you will be unconditionally passing an lvalue, which is not desired.