名稱空間
變體
操作

std::forward

來自 cppreference.com
< cpp‎ | 工具
 
 
 
在標頭檔案 <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-unqualified 函式模板引數的右值引用形式的函式引數)時,此過載將引數以其傳入呼叫函式時的值類別轉發給另一個函式。

例如,如果在一個像下面這樣的包裝器中使用,模板的行為如下所述:

template<class T>
void wrapper(T&& arg)
{
    // arg is always lvalue
    foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}
  • 如果對 wrapper() 的呼叫傳入一個右值 std::string,那麼 T 被推導為 std::string(而不是 std::string&const 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) 將右值轉發為右值,並禁止將右值轉發為左值。

此過載使得可以將表示式(例如函式呼叫)的結果(可能是右值或左值)作為轉發引用引數的原始值類別進行轉發。

例如,如果一個包裝器不僅轉發其引數,而且在其引數上呼叫成員函式,並轉發其結果

// transforming wrapper
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; } // call to this overload is rvalue
    int& get() &  { return i; } // call to this overload is lvalue
};

嘗試將右值轉發為左值,例如透過使用左值引用型別 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)...));
}
 
auto make_B(auto&&... args) // since C++20
{
    return B(std::forward<decltype(args)>(args)...);
}
 
int main()
{
    auto p1 = make_unique1<A>(2); // rvalue
    int i = 1;
    auto p2 = make_unique1<A>(i); // lvalue
 
    std::cout << "B\n";
    auto t = make_unique2<B>(2, i, 3);
 
    std::cout << "make_B\n";
    [[maybe_unused]] B b = make_B(4, i, 5);
}

輸出

rvalue overload, n=2
lvalue overload, n=1
B
rvalue overload, n=2
lvalue overload, n=1
rvalue overload, n=3
make_B
rvalue overload, n=4
lvalue overload, n=1
rvalue overload, n=5

[編輯] 參閱

(C++11)
將引數轉換為亡值
(函式模板) [編輯]
如果移動建構函式不丟擲異常,則將引數轉換為亡值
(函式模板) [編輯]