dev - c++17
El constructor predeterminado impide llamar a emplace_back (1)
Es un error libstdc ++ (edición: reportado como error 69478 ).
Brevemente, std::vector
libstdc ++, como relevante aquí, usa std::uninitialized_copy
(emparejado con mover iteradores) para mover elementos en la reasignación, que se reduce a std::copy
si el tipo es trivial y los tipos de referencia de los iteradores son asignables (Es decir, el operador de asignación que se usaría conceptualmente es utilizable).
Luego, el std::copy
para punteros a tipos triviales (o en nuestro caso, un move_iterator
envuelve un puntero) se optimiza a su vez en una llamada a memmove
junto con una verificación de is_copy_assignable
. Por supuesto, esa comprobación es incorrecta en este caso, ya que la uninitialized_copy
, junto con los iteradores de movimiento, solo requiere que la cosa se pueda construir.
Cuando no tienes un constructor predeterminado o si el constructor predeterminado está definido por el usuario, entonces la clase no es trivial, por lo que no tocas la ruta del código que desencadena este error.
Parece que agregar un constructor predeterminado impide llamar a emplace_back
y genera el mensaje de error: "error de aserción estática: el tipo no es asignable" (gcc 5.3 con -std = c ++ 14). Aquí hay un código simple que ilustra el problema:
class A {
public:
int a;
A() = default;
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error: type is not assignable
return 0;
}
Al eliminar el constructor por defecto, el error desaparece! Además, si se define el constructor predeterminado (incluso si no hace nada), el error también desaparece:
class A {
public:
int a;
A() {
}
A(int a) {
this->a = a;
}
A(A const & a) = delete;
A& operator =(A const & a) = delete;
A(A && a) = default;
A& operator =(A && a) = default;
};
int main() {
A b;
A a(4);
std::vector<A> vec;
vec.emplace_back(std::move(a)); // Error gone
return 0;
}
Parece que "A () = por defecto;" Es lo que está causando el problema. ¿Este comportamiento normal es parte del compilador o es un error?