std::forward
提供: cppreference.com
<tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
<tbody class="t-dcl-rev t-dcl-rev-num ">
</tbody><tbody>
</tbody>
| ヘッダ <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 is always lvalue
foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}
wrapper()の呼び出しに右辺値のstd::stringを渡した場合、Tは (std::string&やconst 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) 右辺値を右辺値として転送し、右辺値が左辺値として転送されることを防ぎます。
このオーバーロードは、式 (関数呼び出しなど) の結果 (右辺値かもしれないし左辺値かもしれない) を、転送参照引数の元々の値カテゴリとして転送することを可能とします。
例えば、 wrapper が引数をただ転送するだけでなく、引数のメンバ関数を呼び、その結果を転送する場合、
// 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 のコンストラクタ引数への完全転送をデモンストレーションします。 また、パラメータパックの完全転送もデモンストレーションします。
Run this code
#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); // rvalue
int i = 1;
auto p2 = make_unique1<A>(i); // lvalue
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
計算量
一定。
関連項目
(C++11) |
右辺値参照を取得します (関数テンプレート) |
(C++11) |
ムーブコンストラクタが例外を投げない場合、右辺値参照を取得します (関数テンプレート) |