¿Puede sizeof (enum) diferir de sizeof (std :: subyacente_tipo <Enum> :: type)?

16

Recientemente apareció en una revisión de código que en el siguiente ejemplo:

enum class A : uint8_t
{
    VAL1, VAL2 
};

...
std::vector<A> vOfA; // Assume this is sized and full of some stuff.
std::memcpy(wire_buffer, vOfA.data(), vOfA.size() * sizeof(A));

Deberíamos estar usando en sizeof(std::underlying_type<A>::type)lugar de sizeof(A). ¿Es posible que estos puedan ser diferentes? ¿Alguien tiene una cita estándar que garantice esto?

Fantástico Sr. Fox
fuente
¿ Vincular cuál es el tamaño de los datos de tipo enum en C ++? (que debe hacerse para cubrir los ámbitos también :-).
Bellota
3
Incluso si son del mismo tamaño (que es más que probable), ¿cuál es el argumento en contra del uso sizeof(A)? Además: si tienen un tamaño diferente (poco probable), el uso sizeof(std::underlying_type<A>)sería simplemente incorrecto.
Sander De Dycker
1
sizeof(std::underlying_type<A>)es probablemente 1. Quiso decir ::type?
LF
1
@SanderDeDycker Sí, cuando se trata de As, uno definitivamente quiere usar sizeof(A)y el código no debería importar qué tipo de tipo Aes.
Bellota
@LF Sí, error tipográfico. El título lo tenía correcto.
Fantástico Mr Fox

Respuestas:

12

En C ++ 03 estaba garantizado (bueno, para enumeraciones sin ámbito de todos modos).

[dcl.enum] Declaraciones de enumeración (énfasis mío)

6 El tipo subyacente de una enumeración es un tipo integral que puede representar todos los valores de enumerador definidos en la enumeración. Si ningún tipo integral puede representar todos los valores del enumerador, la enumeración está mal formada. Se define la implementación del tipo integral que se usa como el tipo subyacente para una enumeración, excepto que el tipo subyacente no debe ser mayor que int a menos que el valor de un enumerador no pueda caber en un int o unsigned int. Si la lista de enumeradores está vacía, el tipo subyacente es como si la enumeración tuviera un único enumerador con valor 0. El valor de sizeof()aplicado a un tipo de enumeración, un objeto de tipo de enumeración o un enumerador es el valor de sizeof()aplicado a tipo subyacente .

Luego vino n2347 , el documento que se adoptó para las enumeraciones fuertemente tipadas ( enum class) y otras mejoras a las enumeraciones sin ámbito, y tenía la oración en negrita eliminada. Curiosamente, una versión anterior de la propuesta, n2213 , tenía un reemplazo para la oración eliminada. Pero no se convirtió en la versión que se adoptó.

Entonces, en C ++ moderno, no hay obligación de que los tamaños sean los mismos. Aunque desde un punto de vista práctico, es poco probable que las implementaciones hayan cambiado el comportamiento prescrito por C ++ 03 para los tamaños de enumeración.

Se podría considerar un defecto en el estándar.

StoryTeller - Unslander Monica
fuente
2
¿Cómo se puede garantizar algo en C ++ 03 para una función que no existía en el lenguaje? oO
ligereza corre en órbita el
44
@LightnessRaceswithMonica: la noción de un tipo subyacente no es nueva. Es solo que C ++ 11 le permitió especificarlo usted mismo.
StoryTeller - Unslander Monica
Yo sé eso. La noción de un enum scoped ( enum class) es nueva.
Carreras de ligereza en órbita el
@LightnessRaceswithMonica: creo que uno puede criticar la propuesta aquí. Hizo dos cosas, introdujo enumeraciones de ámbito y permitió que todas las enumeraciones (no solo las de ámbito) tuvieran establecido su tipo subyacente. De ahí la "garantía" en C ++ 03.
StoryTeller - Unslander Monica
1
@ StoryTeller-UnslanderMonica Sí, creo que la pregunta es la misma, con o sin alcance.
Fantástico Mr Fox