_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++標準で定義されていますか?
_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オーバーロードが削除されていることが判明したため、エラーが発生します。
お役に立てば幸いです。
関数を=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] ここで強調されている文のトーンは、実際には必須です。この標準では、関数=delete
dの宣言は、他の宣言の前に最初に表示する必要があると指示されています。しかし、それでも、関数を削除すると関数も宣言されるという事実をサポートします。