次のクラスを検討してください。
struct with_copy {
with_copy() = default;
with_copy(with_copy const&) {}
with_copy& operator=(with_copy const&) { return *this; }
};
struct foo {
with_copy c;
std::unique_ptr<int> p;
};
with_copy
コピーコンストラクターはありますか? はい。明示的に定義されていました。with_copy
移動コンストラクターはありますか? いいえ。明示的なコピー コンストラクターは、それが生成されないようにします。with_copy
削除された移動コンストラクターはありますか? いいえ。移動コンストラクターがないことは、削除されたコンストラクターがあることと同じではありません。削除された移動コンストラクターは、コピーに退化するのではなく、不適切な形式で移動しようとします。with_copy
コピー可能ですか?はい。そのコピー コンストラクターはコピーに使用されます。with_copy
可動ですか?はい。そのコピー コンストラクターは移動に使用されます。
...そして今、トリッキーなもの。
foo
コピーコンストラクターはありますか? はい。unique_ptr
の削除されたコピーコンストラクターを呼び出すため、デフォルトの定義が不適切な形式になるため、削除されたものがあります。foo
移動コンストラクターはありますか? GCC は「はい」と答え、clang は「いいえ」と答えます。foo
削除された移動コンストラクターはありますか? GCCとclangの両方がノーと言います。foo
コピー可能ですか?いいえ。そのコピー コンストラクターは削除されます。foo
可動ですか?GCC は「はい」と答え、clang は「いいえ」と答えます。
(構築ではなく代入を考慮する場合、動作は似ています。)
私が見る限り、GCC は正しいです。foo
には、各メンバーに対して移動を実行する移動コンストラクターが必要です。このwith_copy
場合、これはコピーに退化します。Clang の動作は非常にばかげているように見えます。2 つの可動メンバーを持つ集合体がありますが、集合体は不動のレンガです。
誰が正しいですか?