2017-09-01 5 views
12

は、標準、std::optional<T>のコピーコンストラクタによると:削除されたようis_copy_constructible_v<T>trueでない限りTがmove-constructibleでないときに、std :: optionalのmove-constructorが削除されないのはなぜですか?

...定義されなければなりません。

しかしstd::optional<T>の移動-コンストラクタ:is_move_constructible_v<T>trueでない限り

...オーバーロードの解決に参加してはなりません。

I understand deleted constructorsstd::optional<T>の移動-コンストラクタは、このようなコードできるようになり、削除ではないことを目的として:

std::optional<X> o1; 
std::optional<X> o2(std::move(o1)); 

が...いくつかの変換シーケンスに頼って仕事をする - o2std::optional<X>&&(私が間違っている場合は私を修正してください)を使用して構築されたタイプAのオブジェクトで構築されます。

しかしTがある場合std::optionalの可能コンストラクタについて、私はつらい時、このユースケースに一致する可能性がものを考え出すを持っている...

はなぜstd::optional<T>の動き-コンストラクタは単にを削除されません動くことはありませんか?明示的にコピーコンストラクタは、これらの例を取るという よりも、それはそれは x値のための最高の試合になるので、コンパイル時エラーになりますことを意味し削除するには

答えて

11

例:

#include <utility> 

struct X 
{ 
    X() = default; 
    X(const X&) = default; 
    X(X&&) = delete; 
}; 

int main() 
{ 
    X a; 
    X b(std::move(a)); 
} 

このようなものになります:

'X::X(X &&)': attempting to reference a deleted function 

明示的に削除された機能は、まだオーバーロード 決議に参加し、最高の試合になることができます。たとえば、特定のコンバージョンを無効にするには、 が便利です。

+0

したがって、 'T'がコピー可能だが移動不可能な場合は、x値から' optional'を構築することができますか? – Holt

+0

@Holt:正確に。 – sp2danny

+0

'T'がmove-constructibleでない場合、move-constructorをオーバーロード解決から除外するように宣言する必要がありますか? '= default'ですか? –

4

委員会は実際にコピー可能だが動かない嫌悪には関心がない。例えば、「病理学」のようなタイプおよびそれを「狂気」としてそれをサポートする初期の試みを特徴付けたLWG issue 2768の議論を参照されたい。

一般的に、この種類のもののデフォルトの表現は、コールをトラップする特定の理由がない限り(「LWG issue 2766」などのような不適切な副作用を引き起こす可能性があります) LWG issue 2993として)。コピースペシャルメンバにとっては、単にコンセプトの前に行うことはできません。したがって、「削除済みとして定義された」を使用しなければなりませんでした。移動特別会員の場合、OTOHは「明示的に削除された移動」と「暗黙的に削除された既定の移動」の間に大きな違いがあるため、「削除済みとして定義された」とは十分に正確ではありません。

LWG issue 2958も参照してください。

関連する問題