コピーおよび移動コンストラクターがいわゆるdone in で呼び出されないため、コンパイラーが以下のコードでコピー省略を行っていることを理解できます。実際の例を参照してください。copy-initialization
main()
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) { std::cout << "move ctor" << '\n'; }
};
int main() {
S s = S();
}
しかし、以下のように移動コンストラクターを削除すると、コードがコンパイルされない理由がわかりません。
#include <iostream>
struct S {
S() = default;
S(const S&) { std::cout << "copy ctor" << '\n'; }
S(S&&) = delete;
};
int main() {
S s = S();
}
§12.8/32 (N4140) には、この場合、コピー コンストラクターの使用または省略を禁止するものは見つかりません。これは、§12.8/32 で私の注意を喚起した文であり、オーバーロードの解決でコピー コンストラクターを考慮する必要があることを示しているようです。
最初のオーバーロードの解決が失敗したか実行されなかった場合、または選択されたコンストラクターの最初のパラメーターの型がオブジェクトの型への右辺値参照 (おそらく cv 修飾) でない場合、オブジェクトを左辺値。
編集
以下のTCによるコメントの 1 つから、コピーされるオブジェクトが右辺値で指定されている場合、コンパイラは、§12.8/32 に従って、コピー コンストラクターをコピーの候補と見なさないことを理解しています。とにかくコピーは省略されますが。つまり、最終結果はs
、デフォルトのコンストラクターを使用したオブジェクトの構築になります。代わりに、この状況では、標準は (どこで??) コードの形式が正しくないことを義務付けています。このスキームに対する私の理解が完全に間違っていない限り、それは私には意味がありません。