首页 > 解决方案 > 将参数包传递给另一个可变参数模板函数时是否必须使用 std::forward

问题描述

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

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)...); }

标签: c++variadic-templatesperfect-forwarding

解决方案


你需要使用forward. forward看起来像这样:

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,您将无条件地传递一个左值,这是不希望的。


推荐阅读