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.