std::move
2013 年の GoingNative の講演で、Scott Meyersは、生成されたコードが実際に移動を実行するという保証はないことを指摘しました。
例:
void foo(std::string x, const std::string y) {
std::string x2 = std::move(x); // OK, will be moved
std::string y2 = std::move(y); // compiles, but will be copied
}
ここでは、ムーブ コンストラクターを適用できませんが、オーバーロードの解決のために、代わりに通常のコピー コンストラクターが使用されます。このフォールバック オプションは、C++98 コードとの下位互換性にとって重要な場合がありますが、上記の例では、プログラマが意図したものではない可能性が高いです。
移動コンストラクターが呼び出されるようにする方法はありますか?
たとえば、巨大な行列を移動するとします。アプリケーションが移動するマトリックスに本当に依存している場合、移動が不可能な場合にすぐにコンパイル エラーが発生するのは素晴らしいことです。(そうしないと、パフォーマンスの問題が単体テストを簡単にすり抜ける可能性があり、プロファイリングを行った後にのみ発見されます。)
これを保証された動きと呼びましょうstrict_move
。次のようなコードを記述できるようにしたいと考えています。
void bar(Matrix x, const Matrix y) {
Matrix x2 = strict_move(x); // OK
Matrix y2 = strict_move(y); // compile error
}
出来ますか?
編集:
素晴らしい答えをありがとう!私の質問を明確にするための正当な要求がいくつかありました。
strict_move
入力が const の場合は失敗しますか?strict_move
結果が実際の移動操作につながらない場合 (コピーが移動と同じくらい高速である場合でもconst complex<double>
)、失敗する必要がありますか?- 両方?
私の最初のアイデアは非常に漠然としていました。Scott Meyers の例は非常に憂慮すべきものだと考えたので、コンパイラでそのような意図しないコピーを防ぐことができるかどうか疑問に思いました。
Scott Meyers は講演の中で、一般的なコンパイラの警告はオプションではないと述べました。代わりに、「これは常に移動操作になる必要があり、コピーはこの特定の型には高すぎると 100% 確信しています」のようなものをコンパイラに伝えたいと考えています。
strict_move
したがって、どちらの場合も失敗するはずだと率直に言ったでしょう。その間、私は何が最善かわかりません。私が考慮しなかった別の側面はnoexcept
.
私の側では、 の正確なセマンティクスstrict_move
はオープンです。重大な欠点を持たずに、コンパイル時の愚かな間違いを防ぐのに役立つものはすべて問題ありません。