# std::forward

< cpp‎ | utility

定义于头文件 `<utility>` |  |
| (1) |
template< class T > T&& forward( typename std::remove_reference<T>::type& t ) noexcept; |  | (C++11 起) (C++14 前)
template< class T > constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept; |  | (C++14 起)
| (2) |
template< class T > T&& forward( typename std::remove_reference<T>::type&& t ) noexcept; |  | (C++11 起) (C++14 前)
template< class T > constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept; |  | (C++14 起)

1) 转发左值为左值或右值，依赖于 T

当 `t` 是转发引用（作为到无 cv 限定函数模板形参的右值引用的函数实参），此重载将参数以在传递给调用方函数时的值类别转发给另一个函数。

例如，若用于如下的包装器，则模板表现为下方所描述：

    template<class T>
    void wrapper(T&& arg)
    {
        // arg 始终是左值
        foo(std::forward<T>(arg)); // 转发为左值或右值，依赖于 T
    }

- 若对 `wrapper()` 的调用传递右值 `std::string` ，则推导 `T` 为 `std::string` （非 `std::string&` 或 `std::string&&` ，且 `std::forward` 确保将右值引用传递给 `foo` 。
- 若对 `wrapper()` 的调用传递 const 左值 `std::string` ，则推导 `T` 为 `const std::string&` ，且 `std::forward` 确保将 const 左值引用传递给 `foo` 。
- 若对 `wrapper()` 的调用传递非 const 左值 `std::string` ，则推导 `T` 为 `std::string&` ，且 `std::forward` 确保将非 const 左值引用传递给 `foo` 。

2) 转发右值为右值并禁止右值的转发为左值

此重载令转发表达式（如函数调用）的结果可行，结果可以是右值或左值，同转发引用参数的原始值类别。

例如，若包装器不仅转发其参数，还在参数上调用成员函数，并转发其结果：

    // 转换包装器
    template<class T>
    void wrapper(T&& arg)
    {
        foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
    }

其中 arg 的类型可以是

    struct Arg
    {
        int i = 1;
        int  get() && { return i; } // 此重载的调用为右值
        int& get() &  { return i; } // 此重载的调用为左值
    };

试图转发右值为左值，例如通过以左值引用类型 T 实例化形式 (2) ，会产生编译时错误。

### 注意

转发引用背后的特殊规则（ `T&&` 用作函数参数）见模板实参推导，其他细节见转发引用。

### 参数

t | - | 要转发的对象

### 返回值

static_cast<T&&>(t)

### 示例

此示例演示参数到类 `T` 构造函数实参的完美转发。并展示参数包的完美转发。

    #include <iostream>
    #include <memory>
    #include <utility>

    struct A {
        A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; }
        A(int& n)  { std::cout << "lvalue overload, n=" << n << "\n"; }
    };

    class B {
    public:
        template<class T1, class T2, class T3>
        B(T1&& t1, T2&& t2, T3&& t3) :
            a1_{std::forward<T1>(t1)},
            a2_{std::forward<T2>(t2)},
            a3_{std::forward<T3>(t3)}
        {
        }

    private:
        A a1_, a2_, a3_;
    };

    template<class T, class U>
    std::unique_ptr<T> make_unique1(U&& u)
    {
        return std::unique_ptr<T>(new T(std::forward<U>(u)));
    }

    template<class T, class... U>
    std::unique_ptr<T> make_unique2(U&&... u)
    {
        return std::unique_ptr<T>(new T(std::forward<U>(u)...));
    }

    int main()
    {
        auto p1 = make_unique1<A>(2); // 右值
        int i = 1;
        auto p2 = make_unique1<A>(i); // 左值

        std::cout << "B\n";
        auto t = make_unique2<B>(2, i, 3);
    }

输出：

    rvalue overload, n=2
    lvalue overload, n=1
    B
    rvalue overload, n=2
    lvalue overload, n=1
    rvalue overload, n=3

### 复杂度

常数

### 参阅

move (C++11) | 获得右值引用 (函数模板)
move_if_noexcept (C++11) | 若移动构造函数不抛出则获得右值引用 (函数模板)