web-dev-qa-db-ja.com

C ++ 11で削除されたメンバー関数の正確なセマンティクスは何ですか?

_struct A
{
    A();

    A(const A&);
    A& operator =(const A&);

    A(A&&) = delete;
    A& operator =(A&&) = delete;
};

struct B
{
    B();

    B(const B&);
    B& operator =(const B&);    
};

int main()
{
    A a;
    a = A(); // error C2280

    B b;
    b = B(); // OK
}
_

私のコンパイラはVC++ 2013RCです。

エラーC2280: 'A&A :: operator =(A &&)':削除された関数を参照しようとしています

A& operator =(const A&);が削除されたときにコンパイラがA& operator =(A&&)を試行しないのはなぜですか?

この動作はC++標準で定義されていますか?

45
xmllmx
_a = A(); // error C2280
_

右側の式は一時的なものであり、operator=(A&&)を検索し、削除されたことを確認します。したがって、エラー。これ以上の検索はありません。

_=delete_はnotは「私を使わないで、代わりにnext最高のものを使う」という意味です。それはむしろ、「私を使わないでくださいあなたが私を必要とするとき —代わりに野生で一人でいる」という意味です。

これは別の例です。クラスXのインスタンスをlong他のタイプなしのみで作成したい場合(longに変換されても!)、宣言します_class X_ as:

_struct X
{
     X(long arg); //ONLY long - NO int, short, char, double, etc!

     template<typename T>
     X(T) = delete;
};

X a(1);  //error - 1 is int 
X b(1L); //ok    - 1L is long
_

つまり、オーバーロードの解決は前に実行コンパイラは_=delete_の部分を認識します—したがって、selectedオーバーロードが削除されていることが判明したため、エラーが発生します。

お役に立てば幸いです。

70
Nawaz

関数を=deleteすると、実際にはその定義が削除されます。

8.4.3削除された定義[dcl.fct.def.delete]

1 フォームの関数定義:

attribute-specifier-seqopt decl-specifier-seqopt declarator = delete;

削除された定義と呼ばれます。定義が削除された関数は、削除された関数とも呼ばれます。

しかしそうすることで、あなたもその関数を宣言しています。標準からの引用 [1]

4 削除された関数は暗黙的にインラインです。 [注:削除された定義には、単一定義規則(3.2)が適用されます。 —end note] 関数の削除された定義は、関数の最初の宣言になります [...]

したがって、a = A()を実行すると、コンパイラは宣言されているため、実際にはA::operator=(A&&)に解決されます(A&&はr-に対して「より拘束力がある」ため、A::operator(const A&)ではありません)。値)。ただし、その定義が削除されているため、行の形式が正しくありません。

2 削除された関数を宣言する以外に、暗黙的または明示的に参照するプログラムは、形式が正しくありません。


[1] ここで強調されている文のトーンは、実際には必須です。この標準では、関数=deletedの宣言は、他の宣言の前に最初に表示する必要があると指示されています。しかし、それでも、関数を削除すると関数も宣言されるという事実をサポートします。

23
Mark Garcia