Vector de objetos const dando error de compilación


He declarado lo siguiente en mi código

vector <const A> mylist; 

Obtengo el siguiente error de compilación -

new_allocator.h:75: error: `const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const \[with _Tp = const A]' and `_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const A]' cannot be overloaded

Pero si declare -

vector <A> mylist;

Mi código compila.

¿Const no está permitido en este contexto?

Estoy copiando mi código aquí para la referencia de todos -

#include <iostream>
#include <vector>

using namespace std;
class A
{
public:
    A () {cout << "default constructor\n";}
    A (int i): m(i) {cout << "non-default constructor\n";}

private:
    int m;
};

int main (void)
{
    vector<const A> mylist;

    mylist.push_back(1);

    return 0;
}
Author: YSC, 2013-06-26

2 answers

Los elementos en un vector deben ser asignables (o, en versiones más recientes del estándar, móviles). const los objetos no son asignables, por lo que intentar almacenarlos en un vector fallará (o al menos puede fallar fail el código no es válido, pero un compilador es libre de aceptarlo de todos modos, si así lo desea, aunque la mayoría de los programadores generalmente preferirían que el código no válido sea rechazado).

Supongo que para los verdaderamente pedantes, si lo quisieras lo suficiente, podrías definir un tipo que fuera asignable a pesar de ser const, algo como esto:

class ugly { 
    mutable int x;
public:
    ugly const &operator=(ugly const &u) const { 
        x = u.x;
        return *this;
    }
};

Creo que debería ser capaz de almacenar artículos de este tipo en un vector a pesar de que son const. Una prueba rápida de crear un vector de estos tiene éxito con VC++. Esto falló con algunos compiladores más antiguos (por ejemplo, falló con g++ 4.8.1), pero funciona con otros razonablemente recientes (VC++ de al menos 2015, g++ de al menos 5.4 y clang++ de al menos 4.0 though aunque no he intentado rastrear la primera versión de cada uno que lo apoyaba).

Para un compilador actual, un tipo que soporta mover objetos const probablemente funcionaría igual de bien. Pero, por si acaso no era obvio: esto te permite modificar un objeto aunque esté marcado const. Eso es claramente una violación directa de las expectativas de cualquier usuario razonable, por lo que en su mayoría es un problema, no una solución.

 28
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-23 22:30:43

El uso del método push_back es el problema. emplace_back compilará. Otra alternativa (dependiendo de toda la situación que no describa aquí) sería usar un vector<A const&> si los elementos insertados tienen una vida fuera del vector. Los elementos en un vector no necesitan ser asignables, pero cuando no lo son, algunas funciones miembro y algoritmos no pueden ser utilizados.

Explicación :

push_back se supone que primero por defecto-construir una A en el vector, luego asigne (usando copy-construct) la referencia dada. Esto rompe su calificación const, por lo tanto no compila.

emplace_back usa "perfect forwarding" para invocar el constructor real directamente en su lugar.

 11
Author: lip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 21:34:09