Los requisitos del contenedor han cambiado de C ++ 03 a C ++ 11. Mientras que C ++ 03 tenía requisitos generales (p. Ej., Copia de construcción y asignabilidad para vector), C ++ 11 define requisitos detallados en cada operación de contenedor (sección 23.2).
Como resultado, puede, por ejemplo, almacenar un tipo que es copia-construible pero no asignable, como una estructura con un miembro constante, en un vector siempre que solo realice ciertas operaciones que no requieren asignación (construcción y push_back
son tales operaciones ; insert
no es).
Lo que me pregunto es: ¿significa esto que el estándar ahora lo permite vector<const T>
? No veo ninguna razón por la que no debería const T
, al igual que una estructura con un miembro constante, es un tipo que es copia construible pero no asignable, pero puede que me haya perdido algo.
(Parte de lo que me hace pensar que me he perdido algo es que el tronco gcc se bloquea y se quema si intenta crear una instancia vector<const T>
, pero está bien vector<T>
si T tiene un miembro constante).
address
funciones miembro sobrecargadas en el asignador predeterminado: cuando T es constante, estas dos sobrecargas tienen la misma firma. Una forma fácil de corregir esto sería especializarsestd::allocator<const T>
y eliminar una de las sobrecargas.push_back
. Pero si el diseño no lo permite, es mejor que no lo hagamos. Solo tenía curiosidad.std::vector<const T>
exactamente porque es muy similar aconst std::vector<T>
, pero sin las implicaciones negativas de este último para la clase que lo tiene. De hecho,std::vector<const T>
es EXACTAMENTE lo que necesito semánticamente en la mayoría de los casos en los que usovector
. Ahora tengo que dejarloconst
, junto con la fiabilidad que proporciona.Actualizar
Bajo la respuesta aceptada (y correcta) comenté en 2011:
Con el próximo borrador de C ++ 17 me parece que ahora lo hemos legalizado
vector<const T>
, y también creo que lo hemos hecho accidentalmente . :-)P0174R0 elimina las
address
sobrecargasstd::allocator<T>
. P0174R0 no menciona el apoyostd::allocator<const T>
como parte de su justificación.Corrección
En los comentarios a continuación, TC señala correctamente que las
address
sobrecargas están obsoletas , no eliminadas. Culpa mía. Los miembros obsoletos no aparecen en 20.10.9 dondestd::allocator
se define, sino que son relegados a la sección D.9. Me olvidé de escanear el Capítulo D en busca de esta posibilidad cuando publiqué esto.Gracias TC por la corrección. Contemplé eliminar esta respuesta engañosa, pero tal vez sea mejor dejarlo con esta corrección para que tal vez evite que alguien más lea mal la especificación de la misma manera que yo.
fuente
address
.vector<const T>
:)Aunque ya tenemos muy buenas respuestas sobre esto, decidí contribuir con una respuesta más práctica para mostrar qué se puede y qué no se puede hacer.
Entonces esto no funciona:
vector<const T> vec;
Simplemente lea las otras respuestas para comprender por qué. Y, como habrás adivinado, esto tampoco funcionará:
vector<const shared_ptr<T>> vec;
T
ya no esconst
, perovector
tieneshared_ptr
s, noT
s.Por otro lado, esto hace el trabajo:
vector<const T *> vec; vector<T const *> vec; // the same as above
Pero en este caso, const es el objeto al que se apunta, no el puntero en sí (que es lo que almacena el vector). Esto sería equivalente a:
vector<shared_ptr<const T>> vec;
Lo cual está bien.
Pero si ponemos
const
al final de la expresión, ahora convierte el puntero en aconst
, por lo que lo siguiente no se compilará:vector<T * const> vec;
Un poco confuso, estoy de acuerdo, pero te acostumbras.
fuente
Complementando las otras respuestas, otro enfoque es utilizar:
vector<unique_ptr<const T>> vec;
Si es el caso en el que desea hacer valer que solo
vec
tiene la propiedad de sus elementos. O si desea una dinámica de mover elementosvec
y, en algún momento, moverlos.Como a cabo en punta, puntero
const
semántica puede ser confuso, peroshared_ptr
yunique_ptr
no lo son.const unique_ptr<T>
es un puntero constante yunique_ptr<const T>
es un puntero constante como cabría esperar.fuente