将参数包传递给另一个可变参数模板函数时,是否必须使用std :: forward

时间:2019-07-14 19:20:07

标签: c++ variadic-templates perfect-forwarding

如何实现将参数包传递到函数(栏)的函数(foo),该函数最终将参数包传递给类构造函数? 这是代码:

template <typename... Args>
void bar(Args&&... args)
{
    MyObj obj(std::forward<Args>(args)...);
    /* Do something with obj */
}

我是否必须将foo实现为

template <typename... Args>
void foo(Args&&... args)
{ bar(args...); }

template <typename... Args>
void foo(Args&&... args)
{ bar(std::forward<Args>(args)...); }

1 个答案:

答案 0 :(得分:2)

您需要使用forwardforward看起来像这样:

template <class T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept
{
    return static_cast<T&&>(t);
}

forward的另一个重载,但在这里无关紧要。)

对于模板参数包Arg的每个元素ArgsArg可以是:(T是非引用类型)

  • T&,如果参数是非常量左值,则参数的类型为T&;或

  • const T&(如果参数是const左值),则参数的类型为const T&;或

  • T(如果参数是右值),则参数的类型为T&&

在第一种情况下,forward<Arg>(arg)实例化为:

constexpr T& forward(T& t) noexcept
{
    return static_cast<T&>(t);
}

导致要传递的非常量左值。

在第二种情况下,forward<Arg>(arg)实例化为:

constexpr const T& forward(const T& t) noexcept
{
    return static_cast<const T&>(t);
}

产生要传递的const左值。

在最后一种情况下,forward<Arg>(arg)实例化为:

constexpr T&& forward(T&& t) noexcept
{
    return static_cast<T&&>(t);
}

导致要传递的右值。

在所有这三种情况下,值类别都会保留,并且值会在修改为bar的情况下转发。

如果您不使用forward,则将无条件传递不需要的左值。