std::forward
変数で使用するauto&&
ことが、それらの変数を渡して移動を許可する正しい方法であるかどうかを理解しようとしています。
関数があると仮定します:
void moveWidget(Widget&& w);
そして呼び出し元 - 右辺値と左辺値を参照する 2 つの変数:
Widget w;
auto&& uniRefLV = w; // lvalue initialiser,
// uniRefLV's type is Widget&
auto&& uniRefRV = std::move(w); // rvalue initialiser,
// uniRefRV's type is Widget&&
型推論が行われているため、型の変数auto&&
がユニバーサル参照であることはわかっています。これは、uniRefRV
との両方uniRefLV
が普遍的な参照であることを意味します。
私の例では、右辺値と左辺値であることは明らかですuniRefRV
が、概念的にはどちらも普遍的な参照であり、定義が異なる場合、右辺値または左辺値のいずれかを表すことができます。uniRefLV
moveWidget()
ここで、これらのユニバーサル参照型を呼び出して完全転送したいと思います。ガイドライン (Scott Meyers による) は次のように述べています。
を介して右辺値参照を渡し、を介して
std::move
ユニバーサル参照を返しstd::forward
ます。
そして、私がガイドラインを完全に誤解していない限り、それを使用するのは理にかなっているように思えますstd::forward
。しかし、考えられるすべての選択肢を考えてみましょう。
// (1) std::move:
moveWidget(std::move(uniRefLV)); // Compiles and looks fine
// but violates the guideline?
// (unconditionally casts lvalue to rvalue)
moveWidget(std::move(uniRefRV)); // Same as above - but not an issue here
// as we cast rvalue to rvalue
// (2) std::forward with Widget:
moveWidget(std::forward<Widget>(uniRefLV)); // Compiles, follows the guideline
// but doesn't look right - what if
// we didn't know Widget's type?
moveWidget(std::forward<Widget>(uniRefRV)); // Same as above
// (3) std::forward with decltype:
moveWidget(std::forward<decltype(uniRefLV)>(uniRefLV)); // Fails to compile! (VC10)
// follows the guideline
// has nice and short syntax :)
moveWidget(std::forward<decltype(uniRefRV)>(uniRefRV)); // Compiles fine
uniRefLV
両方の参照を同等に扱うべきだと思いますuniRefRV
か? また、完全な転送のために 3 つのオプションのどれを使用する必要がありますか?