10

の実装はstd::move基本的に次のようになります。

template<typename T>
typename std::remove_reference<T>::type&&
move(T&& t)
{
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}

のパラメーターstd::moveはユニバーサル参照 (転送参照とも呼ばれますが、ここでは転送しません) であることに注意してください。つまり、std::move左辺値と右辺値の両方を使用できます。

std::string a, b, c;
// ...
foo(std::move(a));       // fine, a is an lvalue
foo(std::move(b + c));   // nonsense, b + c is already an rvalue

しかし、全体のポイントはstd::move右辺値にキャストすることなので、なぜ右辺値にキャストできるのstd::moveでしょうか? std::move左辺値のみを受け入れるとしたら、もっと理にかなっているのではないでしょうか?

template<typename T>
T&&
move(T& t)
{
    return static_cast<T&&>(t);
}

その場合、無意味な式std::move(b + c)によってコンパイル エラーが発生します。

上記の の実装はstd::move、コードが見た目とまったく同じように動作するため、初心者にとってははるかに理解しやすいでしょう: 左辺値を取り、右辺値を返します。ユニバーサル参照、参照の折りたたみ、およびメタ関数を理解する必要はありません。

では、なぜstd::move左辺値と右辺値の両方を取るように設計されたのでしょうか?

4

2 に答える 2

4

痛くない。

コードが結果を右辺値として扱うという保証を確立しているだけです。確かに、すでに右辺値になっているものを処理するときにエラーが発生するように std::move を書くことができますが、その利点は何ですか?

作業するタイプが必ずしもわからない一般的なコードでは、「タイプが右辺値である場合は、std::move 以外に何もしない」の束から表現力のどのような利点を抽出しますか? 「これを右辺値と考えることができると約束します」と簡単に言うことができる場合、どこにでも貼り付けられます。

あなたはそれを自分で言いました、それはキャストにすぎません。引数が意図した型と既に一致している場合、*_cast 操作も失敗するはずですか?

于 2015-03-09T12:27:00.210 に答える