overload operator equal assignment c++ c++11 overloading semantics language-lawyer

equal - function operator c++



¿Cuál es la semántica exacta de una función eliminada en C++ 11? (2)

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 }

Mi compilador es VC ++ 2013 RC.

error C2280: ''A & A :: operator = (A &&)'': intentando hacer referencia a una función eliminada

Me pregunto por qué el compilador no prueba A& operator =(const A&); cuando A& operator =(A&&) se borra?

¿Está este comportamiento definido por el estándar de C ++?


Cuando =delete una función, en realidad estás eliminando su definición .

8.4.3 Definiciones eliminadas [dcl.fct.def.delete]

1 Una definición de la función de la forma:

atributo-especificador-seqopt decl-specifier-seqopt declarator = delete;

Se llama una definición eliminada . Una función con una definición eliminada también se denomina función eliminada .

Pero al hacerlo, también estás declarando esa función. Citando de la norma [1] :

4 Una función eliminada está implícitamente en línea. [Nota: la regla de una definición (3.2) se aplica a las definiciones eliminadas. —Encripción] Una definición eliminada de una función será la primera declaración de la función [...]

Y así, al hacer a = A() , el compilador en realidad se resuelve en A::operator=(A&&) porque se ha declarado (no A::operator(const A&) porque A&& es "más vinculante" a los valores r ). Sin embargo, con su definición siendo eliminada, la línea está mal formada.

2 Un programa que hace referencia a una función eliminada de manera implícita o explícita, que no sea para declararla, está mal formado.

[1] El tono de la oración enfatizada aquí es realmente imperativo. El estándar indica que declarar una función =delete d primero debe aparecer antes que otras declaraciones de la misma. Pero aún así, apoya el hecho de que eliminar una función también declara la función.


a = A(); // error C2280

La expresión de la derecha es temporal, lo que significa que buscará el operator=(A&&) y verá que se elimina. De ahí el error. No hay más búsqueda.

=delete no significa "no me uses, usa la siguiente mejor". Más bien significa: "No me uses cuando me necesites , en lugar de eso, estar solo en la naturaleza".

Aquí hay otro ejemplo. Si quiero que las instancias de mi clase X se creen solo con long y no con otro tipo (¡incluso si se convierten en largas!), Declararía la class X como:

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

Eso significa que la resolución de sobrecarga se realiza antes de que el compilador vea la parte =delete - y, por lo tanto, se genere un error porque la sobrecarga seleccionada se encuentra eliminada.

Espero que ayude.