std::move の変換マジックの謎を解明する
std::move() を呼び出すと、参照されるrvalue パラメーターは lvalue にバインドできますが、通常は rvalue 参照への付加が制限されます。 std::move() の実装を詳しく調べると、この明らかな矛盾の鍵が明らかになります。
std::move() 実装の分析
洗練されたものから始めるstd::move() のバージョン:
template <typename T> typename remove_reference<T>::type&& move(T&& arg) { return static_cast<typename remove_reference<T>::type&&>(arg); }
ケース 1: 右辺値を使用した move() の呼び出し
次のような右辺値を指定して move() が使用される場合一時オブジェクト:
Object a = std::move(Object()); // Object() is temporary, hence prvalue
結果のテンプレートのインスタンス化は次のようになります:
remove_reference<Object>::type&& move(Object&& arg) { return static_cast<remove_reference<Object>::type&&>(arg); }
remove_reference は T& を T に、または T&& を T に変換し、Object はプレーンな値であるため、最終的な関数の形態は
Object&& move(Object&& arg) { return static_cast<Object&&>(arg); }
名前付き右辺値参照は左辺値として扱われるため、キャストは重要です。
ケース 2: 左辺値を使用した move() の呼び出し
move() が lvalues で呼び出された場合:
Object a; // a is an lvalue Object b = std::move(a);
結果として move() のインスタンス化は次のようになります:
remove_reference<Object&>::type&& move(Object& && arg) { return static_cast<remove_reference<Object&>::type&&>(arg); }
ここでも、remove_reference は Object& を Object に変換し、次の結果が得られます:
Object&& move(Object& && arg) { return static_cast<Object&&>(arg); }
参照折りたたみの本質
Object& && とその lvalue へのバインド機能を理解することが、謎を解く鍵です。 C 11 では、参照の折りたたみに関する特別なルールが導入されており、次のように規定されています。
Object & && = Object & Object & &&& = Object & Object && & = Object & Object && &&& = Object &&
したがって、Object& && は、実際には、簡単に左辺値にバインドできる典型的な左辺値参照である Object& に変換されます。
結果の関数
これらのルールを適用すると、最終的な関数は次のようになります。
Object&& move(Object& arg) { return static_cast<Object&&>(arg); }
右辺値のインスタンス化をミラーリングし、その引数を右辺値参照にキャストすることで、均一な動作が保証されます。 .
remove_reference の重要性
remove_reference の目的は、代替関数を調べると明らかになります。
template <typename T> T&& wanna_be_move(T&& arg) { return static_cast<T&&>(arg); }
左辺値でインスタンス化された場合:
Object& && wanna_be_move(Object& && arg) { return static_cast<Object& &&&>(arg); }
参照折りたたみルールを適用すると、左辺値引数に対して左辺値を返す、使用できない移動のような関数が明らかになります。原因は、remove_reference の欠如であり、右辺値参照への適切な変換が妨げられます。
以上が右辺値参照が右辺値にのみバインドされることになっている場合、 std::move() はどのように左辺値にバインドするのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。