c++ templates stl tr1 c++11

c++ - ¿Está garantizado que std:: array<T, S> es POD si T es POD?



templates stl (3)

§23.3.1:

Una matriz es un agregado (8.5.1) que se puede inicializar con la array a<T, N> = { initializer-list }; sintaxis array a<T, N> = { initializer-list }; donde initializer-list es una lista separada por comas de hasta N elementos cuyos tipos son convertibles a T.

En C ++ 03, POD se definió en términos de agregado: una clase en la que cada subobjeto es nativo o un agregado es POD. Entonces, por compatibilidad con versiones anteriores, una std::array C ++ 0x std::array es POD.

O, para ser anal, se pueden comparar las viñetas de §9 / 5 (que definen la clase trivial) 9/6 (que definen el diseño estándar) y 9/9 (que combinan los requisitos anteriores en POD) con los de 8.5.1 / 1, que define los agregados.

8.5.1:

Un agregado es una matriz o una clase (Cláusula 9) sin constructores proporcionados por el usuario (12.1), sin inicializadores con refuerzo o igual para miembros de datos no estáticos (9.2), no hay miembros de datos no estáticos privados o protegidos ( Cláusula 11), sin clases base (Cláusula 10) y sin funciones virtuales (10.3).

De hecho, los requisitos de la cláusula 9 cubren la array siempre que su tipo de elemento también sea POD y la implementación no declare operator= o se move dentro de la array además de las especificaciones.

Para ser realmente anal, 17.5.2.2 dice

  1. Por el bien de la exposición, las Cláusulas 18 a 30 y el Anexo D no describen los constructores de copia / movimiento, los operadores de asignación o los destructores (no virtuales) con la misma semántica aparente que los que pueden generarse por defecto (12.1, 12.4, 12.8 ).
  2. No se especifica si la implementación proporciona definiciones explícitas para tales firmas de función miembro o para los destructores virtuales que se pueden generar de forma predeterminada.

La nota en el pseudo-código para template class array es

// No explicit construct/copy/destroy for aggregate type

¿ construct/copy/destroy incluye operator= (asignación) o move ? Probablemente debería, pero no creo que, por la lectura más estricta, lo haga.

Tenga en cuenta que esto "afecta" no solo a la POD-ness, sino también a la copia trivial como lo menciona Johannes.

Actualmente estoy escribiendo una biblioteca de edición de memoria en C ++ y para las API de lectura / escritura uso rasgos de tipo (std :: is_pod, std :: is_same) y boost :: enable_if para proporcionar 3 sobrecargas:

  1. Tipos de POD. por ejemplo, MyMem.Read (SomeAddress);
  2. Tipos de cuerdas. por ejemplo, MyMem.Read> (SomeAddress); (Esto realmente no lee una cadena de C ++, lee una cadena de estilo C y la convierte en una cadena de C ++).
  3. Tipos de vectores por ejemplo, MyMem.Read> (SomeAddress, NumElem); (Esto en realidad no lee un vector, sino que lee una matriz de estilo C y lo convierte en un vector).

Las sobrecargas 2 y 3 son simplemente ''envoltorios'' alrededor de la sobrecarga 1. (Entonces, si estás leyendo un std :: vector o std :: basic_string y T no es POD, fallará, como debería).

Recientemente quise usar std :: array para un montón de lecturas y escrituras porque sabía el tamaño de los datos que quería leer y escribir en el momento de la compilación (estaba escribiendo una envoltura alrededor del formato de archivo PE).

Escribí el código para usar std :: array, y luego intenté agregar otra sobrecarga para la detección y el manejo de los tipos de std :: array, pero accidentalmente presioné Compilar y, para mi sorpresa, ¡funcionó!

Actualmente estoy usando MSVC 10 y resulta que para std :: array si T es POD, entonces std :: array es POD. (Lo que significa que puedo usar la sobrecarga 1 y funciona).

Mi pregunta es si esto está garantizado por el estándar de C ++ o se deja para la implementación.

Sé que podría verificar el estándar yo mismo, pero no confío tanto en mí como confío en algunos de los abogados de idiomas en este sitio, así que pensé que sería mejor obtener una ''segunda opinión''. ;)

Gracias

Código de PS disponible aquí (es una biblioteca de sólo encabezado): http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86


Por definición de POD:

9 clases

9 Una estructura POD es una clase que es tanto una clase trivial como una clase de diseño estándar , y no tiene miembros de datos no estáticos de tipo estructura no POD, unión no POD (o matriz de tales tipos). De manera similar, una unión POD es una unión que es a la vez una clase trivial y una clase de diseño estándar, y no tiene miembros de datos no estáticos de tipo estructura no POD, unión no POD (o matriz de tales tipos). Una clase POD es una clase que es una estructura POD o una unión POD.

[Énfasis mío]

std::array satisface todos los requisitos de ser una plantilla de clase de diseño estándar trivial. Así que la respuesta a tu pregunta es sí.


Potatoswatter encontró un error en mis conclusiones. C ++ permite explícitamente que una implementación defina explícitamente un operador de asignación "con la misma semántica aparente". Esto hará que sea un tipo copiable no trivial. Haciéndolo wiki de la comunidad ...

Me parece que no quieres probar contra PODnes, sino contra trivialmente copiable , que es mucho menos restrictivo. Porque así es como los tipos de restricciones C ++ 0x que se pueden usar con memcpy y amigos.

Y aunque no creo que haya garantías sobre la PODness de std::array , existen garantías sobre la copia trivial, como se muestra a continuación (si no tengo un error en las conclusiones). Como sabemos, std::array es un agregado, y los agregados son

Un agregado es una matriz o una clase (Cláusula 9) sin constructores proporcionados por el usuario (12.1), sin inicializadores con refuerzo o igual para miembros de datos no estáticos (9.2), no hay miembros de datos no estáticos privados o protegidos ( Cláusula 11), sin clases base (Cláusula 10) y sin funciones virtuales (10.3).

Mientras que la capacidad de copia trivial se define para una clase que tiene una clase que

  • no tiene constructores de copia no triviales (12.8),
  • no tiene constructores de movimientos no triviales (12.8),
  • no tiene operadores de asignación de copia no triviales (13.5.3, 12.8),
  • no tiene operadores de asignación de movimientos no triviales (13.5.3, 12.8), y
  • Tiene un destructor trivial (12.4).

std::array no tiene destructor (como dice un comentario en la definición de std::array ). Sin embargo, esto no parece seguir de la definición de clases agregadas, a pesar de que el comentario en la definición de clase de std::array afirma eso.

Los 4 requisitos restantes se derivan de la ausencia de bases, funciones virtuales y versiones proporcionadas por el usuario para esas 4 funciones miembro especiales para agregados.