¿C ++ 11 permite vector ?

Los requisitos del contenedor han cambiado de C ++ 03 a C ++ 11. Si bien C ++ 03 tenía requisitos generales (por ejemplo, copia de la capacidad de construcción y de asignabilidad para el vector), C ++ 11 define requisitos precisos en cada operación del contenedor (sección 23.2).

Como resultado, puede, por ejemplo, almacenar un tipo que sea copiable pero no asignable, como una estructura con un elemento 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 permite vector ? No veo ninguna razón por la que no debería – const T , al igual que una estructura con un miembro de const, es un tipo que es copiable pero no asignable, pero es posible que haya pasado algo por alto.

(Parte de lo que me hace pensar que me he perdido algo, es que el tronco gcc se cuelga y quema si intentas crear una instancia del vector , pero está bien con el vector donde T tiene un miembro const).

No, creo que los requisitos del asignador dicen que T puede ser un “tipo de objeto no const, no de referencia”.

No sería capaz de hacer mucho con un vector de objetos constantes. Y un const vector sería casi igual de todos modos.


Muchos años después, esta respuesta rápida y sucia todavía parece atraer comentarios y votos. No siempre está arriba. 🙂

Entonces, para agregar algunas referencias apropiadas:

Para el estándar C ++ 03, que tengo en papel, la Tabla 31 en la sección [lib.allocator.requirements] dice:

T, U any type

No es que ningún tipo realmente funcionó.

Por lo tanto, el siguiente estándar, C ++ 11, dice en un borrador detallado en [allocator.requirements] y ahora en la Tabla 27:

T, U, C any non-const, non-reference object type

que es extremadamente cercano a lo que originalmente escribí arriba de memoria. De eso también se trataba la pregunta.

Sin embargo, en C ++ 14 ( borrador N4296 ), la Tabla 27 ahora dice:

T, U, C any non-const object type

Posiblemente porque una referencia tal vez no sea un tipo de objeto después de todo?

Y ahora en C ++ 17 ( borrador N4659 ) es la Tabla 30 que dice:

T, U, C any cv-unqualified object type (6.9)

Entonces, no solo se excluye el const , sino que también es volatile . Probablemente sean noticias viejas de todos modos, y solo una aclaración.


Consulte también la información de primera mano de Howard Hinnant , que se encuentra justo debajo.

Actualizar

Debajo de la respuesta aceptada (y correcta) que comenté en 2011:

En pocas palabras: no diseñamos contenedores para mantener const T Aunque lo pensé un poco. Y estuvimos muy cerca de hacerlo por accidente. Hasta donde yo sé, el punto de fricción actual es el par de funciones de miembro de address sobrecargadas en el asignador predeterminado: cuando T es const , estas dos sobrecargas tienen la misma firma. Una manera fácil de corregir esto sería especializar std::allocator y eliminar una de las sobrecargas.

Con el próximo borrador de C ++ 17, me parece que ahora hemos legalizado el vector , y también creo que lo hemos hecho accidentalmente . 🙂

P0174R0 elimina las sobrecargas de address de std::allocator . P0174R0 no menciona el soporte de std::allocator como parte de su fundamento.

Corrección

En los comentarios a continuación, TC señala correctamente que las sobrecargas de address están en desuso , no eliminadas. Mi error. Los miembros obsoletos no aparecen en 20.10.9 donde se define std::allocator , sino que se relegan a la sección D.9. Descuidé escanear el Capítulo D para esta posibilidad cuando publiqué esto.

Gracias TC por la corrección. Consideré eliminar esta respuesta engañosa, pero tal vez sea mejor dejarlo con esta corrección para que tal vez evite que alguien más malinterprete las especificaciones de la misma manera que yo.

Aunque ya tenemos muy buenas respuestas sobre esto, decidí contribuir con una respuesta más práctica para mostrar lo que se puede y no se puede hacer.

Entonces esto no funciona:

 vector vec; 

Simplemente lea las otras respuestas para entender por qué. Y, como habrás adivinado, esto tampoco funcionará:

 vector> vec; 

T ya no es const , pero el vector contiene shared_ptr s, no T s.

Por otro lado, esto funciona:

 vector vec; vector 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> vec; 

Lo cual está bien.

Pero si ponemos const al final de la expresión, ahora convierte el puntero en un const , por lo que no se comstackrá lo siguiente:

 vector vec; 

Un poco confuso, estoy de acuerdo, pero te acostumbras.

Complementando las otras respuestas, otro enfoque es usar:

 vector> vec; 

Si es el caso donde desea hacer cumplir, solo el vec tiene la propiedad de sus elementos. O si desea una dinámica de mover elementos a vec y en algún momento moverlos.

Como se señaló, la semántica const puntero puede ser confusa, pero shared_ptr y unique_ptr no lo son. const unique_ptr es un const pointer y unique_ptr es un const pointee como es de esperar.