Sizeof (enum) peut-il différer de sizeof (std :: sous-jacent_type <Enum> :: type)?

16

Récemment apparu dans une revue de code qui dans l'exemple suivant:

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));

Nous devrions utiliser sizeof(std::underlying_type<A>::type)au lieu de sizeof(A). Est-il possible que ceux-ci puissent différer? Quelqu'un at-il un devis standard qui garantit cela?

Fantastique Mr Fox
la source
Lier quelle est la taille d'une donnée de type enum en C ++? (ce qui devrait être fait pour couvrir également les portées :-).
Acorn
3
Même s'ils sont de la même taille (ce qui est probablement le cas), quel est l'argument contre l'utilisation sizeof(A)? Aussi: si elles sont d'une taille différente (peu probable), l'utilisation sizeof(std::underlying_type<A>)serait tout simplement fausse.
Sander De Dycker
1
sizeof(std::underlying_type<A>)est probablement 1. Tu voulais dire ::type?
LF
1
@SanderDeDycker Oui, quand on traite de As, on veut vraiment utiliser sizeof(A)et le code ne devrait pas se soucier de quel type Aest.
Acorn
@LF Oui, faute de frappe. Le titre était correct.
Fantastique Mr Fox

Réponses:

12

En C ++ 03, il était garanti (enfin, pour les énumérations non étendues de toute façon).

[dcl.enum] Déclarations d'énumération (c'est moi qui souligne)

6 Le type sous-jacent d'une énumération est un type intégral qui peut représenter toutes les valeurs d'énumérateur définies dans l'énumération. Si aucun type intégral ne peut représenter toutes les valeurs de l'énumérateur, l'énumération est incorrecte. Il est défini par l'implémentation quel type intégral est utilisé comme type sous-jacent pour une énumération, sauf que le type sous-jacent ne doit pas être supérieur à int sauf si la valeur d'un énumérateur ne peut pas tenir dans un int ou un int non signé. Si la liste d'énumérateurs est vide, le type sous-jacent est comme si l'énumération avait un seul énumérateur avec la valeur 0. La valeur sizeof()appliquée à un type d'énumération, un objet de type énumération ou un énumérateur, est la valeur sizeof()appliquée à la type sous-jacent .

Puis vint n2347 , le document qui a été adopté pour les énumérations fortement typées ( enum class) et d'autres améliorations aux énumérations non étendues, et la phrase en gras a été supprimée. Chose intéressante, une version antérieure de la proposition, n2213 , a remplacé la phrase supprimée. Mais cela n'a pas fait partie de la version qui a été adoptée.

Donc, en C ++ moderne, il n'y a aucune obligation pour que les tailles soient les mêmes. Bien que d'un point de vue pratique, il est peu probable que les implémentations aient changé le comportement prescrit par C ++ 03 pour les tailles d'énumération.

On pourrait le considérer comme un défaut de la norme.

Conteur - Unslander Monica
la source
2
Comment peut-on garantir quelque chose en C ++ 03 pour une fonctionnalité qui n'existait pas dans le langage? oO
Courses de légèreté en orbite
4
@LightnessRaceswithMonica - La notion de type sous-jacent n'est pas nouvelle. C'est juste que C ++ 11 vous a permis de le spécifier vous-même.
Conteur - Unslander Monica
Je le sais. La notion d'enum de portée ( enum class) est nouvelle.
Courses de légèreté en orbite
@LightnessRaceswithMonica - Je pense que l'on peut potentiellement reprocher à la proposition ici. Il a fait deux choses, introduit des énumérations de portée et a permis à toutes les énumérations (pas seulement celles de portée) d'avoir leur type sous-jacent défini. D'où le "garanti" en C ++ 03.
StoryTeller - Unslander Monica
1
@ StoryTeller-UnslanderMonica Ouais, la question est la même je pense, portée ou non.
Fantastique Mr Fox