Kann sich sizeof (enum) von sizeof (std :: zugrunde liegender_Typ <Enum> :: type) unterscheiden?

16

Kürzlich kam in einer Codeüberprüfung, die im folgenden Beispiel:

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

Wir sollten sizeof(std::underlying_type<A>::type)anstelle von verwenden sizeof(A). Ist es möglich, dass sich diese jemals unterscheiden können? Hat jemand ein Standardangebot, das dies garantiert?

Fantastischer Mr. Fox
quelle
Verknüpfen Wie groß sind die Daten eines Aufzählungstyps in C ++? (was gemacht werden sollte, um auch Bereiche abzudecken :-).
Eichel
3
Was ist das Argument gegen die Verwendung, selbst wenn sie dieselbe Größe haben (was höchstwahrscheinlich der Fall ist) sizeof(A)? Außerdem: Wenn sie eine andere Größe haben (unwahrscheinlich), sizeof(std::underlying_type<A>)wäre die Verwendung einfach falsch.
Sander De Dycker
1
sizeof(std::underlying_type<A>)ist wahrscheinlich 1. Meinten Sie ::type?
LF
1
@SanderDeDycker Ja, wenn man sich mit As beschäftigt, möchte man definitiv verwenden sizeof(A)und der Code sollte sich nicht darum kümmern, was für ein Typ es Aist.
Eichel
@LF Ja, Tippfehler. Der Titel hatte es richtig.
Fantastischer Herr Fox

Antworten:

12

In C ++ 03 war dies garantiert (na ja, für Aufzählungen ohne Gültigkeitsbereich sowieso).

[dcl.enum] Aufzählungserklärungen (Hervorhebung von mir)

6 Der zugrunde liegende Typ einer Aufzählung ist ein integraler Typ, der alle in der Aufzählung definierten Aufzählungswerte darstellen kann. Wenn kein integraler Typ alle Enumeratorwerte darstellen kann, ist die Enumeration fehlerhaft. Es ist implementierungsdefiniert, welcher Integraltyp als zugrunde liegender Typ für eine Aufzählung verwendet wird, mit der Ausnahme, dass der zugrunde liegende Typ nicht größer als int sein darf, es sei denn, der Wert eines Enumerators kann nicht in ein int oder ein vorzeichenloses int passen. Wenn die Enumerator-Liste leer ist, ist der zugrunde liegende Typ so, als hätte die Enumeration einen einzelnen Enumerator mit dem Wert 0. Der Wert, der sizeof()auf einen Aufzählungstyp, ein Objekt des Aufzählungstyps oder ein Enumerator sizeof()angewendet wird , ist der Wert von , der auf den angewendet wird zugrunde liegender Typ .

Dann kam n2347 , das Papier, das für stark typisierte Aufzählungen ( enum class) und andere Verbesserungen an nicht abgedeckten Aufzählungen übernommen wurde, und der fett gedruckte Satz wurde entfernt. Interessanterweise hatte eine frühere Version des Vorschlags, n2213 , einen Ersatz für den entfernten Satz. Aber es wurde nicht in die Version aufgenommen, die übernommen wurde.

In modernem C ++ besteht daher keine Verpflichtung, dass die Größen gleich sind. Aus praktischer Sicht ist es jedoch unwahrscheinlich, dass Implementierungen das von C ++ 03 für Aufzählungsgrößen vorgeschriebene Verhalten geändert haben.

Man könnte es als einen Defekt in der Norm betrachten.

Geschichtenerzähler - Unslander Monica
quelle
2
Wie kann in C ++ 03 etwas für eine Funktion garantiert werden, die in der Sprache nicht vorhanden war? oO
Leichtigkeitsrennen im Orbit
4
@LightnessRaceswithMonica - Der Begriff eines zugrunde liegenden Typs ist nicht neu. In C ++ 11 können Sie es nur selbst angeben.
StoryTeller - Unslander Monica
Ich weiß das. Die Vorstellung einer enum ( enum class) mit Gültigkeitsbereich ist neu.
Leichtigkeitsrennen im Orbit
@LightnessRaceswithMonica - Ich denke, man kann den Vorschlag hier möglicherweise bemängeln. Es hat zwei Dinge getan, Aufzählungen mit Gültigkeitsbereich eingeführt und allen Aufzählungen (nicht nur Aufzählungsbereichen) erlaubt, ihren zugrunde liegenden Typ festzulegen. Daher die "Garantie" in C ++ 03.
Geschichtenerzähler - Unslander Monica
1
@ StoryTeller-UnslanderMonica Ja, die Frage ist die gleiche, die ich denke, mit oder ohne Umfang.
Fantastischer Herr Fox