Frage

Ich habe versucht, ein wenig von dem C ++ Standard zu lesen, wie Enum Arbeit herauszufinden. Es gibt tatsächlich mehr als ich ursprünglich dachte.

Für eine scoped Aufzählung, es ist klar, dass der zugrunde liegende Typ int ist, wenn nicht anders mit einer ENUM-Basis-Klausel angegeben (es kann jeden Integral-Typ sein).

enum class color { red, green, blue};  // these are int

Für unscoped Aufzählungen, scheint es, wie der zugrunde liegende Typ kann jeder integralen Typ sein, der funktionieren wird und dass es nicht größer sein als ein int, es sei denn, es sein muss.

enum color { red, green, blue};  // underlying type may vary

Da der zugrunde liegende Typ von unscoped enumarations nicht standardisiert ist, was ist der beste Weg, um mit dem Serialisierung Instanzen eines tun? Bisher Ich habe die Umstellung auf int beim Schreiben dann in eine int Serialisierung und Einstellung meiner enum Variable in einem Schalter beim Lesen, aber es scheint ein bisschen klobig. Gibt es einen besseren Weg?

enum color { red, green, blue };
color c = red;
// to serialize
archive << (int)c;
// to deserialize
int i;
archive >> i;
switch(i) {
  case 0: c = red; break;
  case 1: c = green; break;
  case 2: c = blue; break;
}
War es hilfreich?

Lösung

Ich habe keine C ++ 0x Sachen, damit ich nicht kommentieren kann.

Wie für die Serialisierung, Sie den Schalter nicht brauchen, wenn die Enumeration zurück in das Lesen -. Werfen sie nur auf den Aufzählungstyp

Allerdings habe ich nicht werfen, wenn in den Stream zu schreiben. Dies liegt daran, Ich mag oft einen Operator schreiben << für die Enum so kann ich schlechte Werte fängt geschrieben werden, oder ich kann dann entscheiden, statt eine Zeichenfolge zu schreiben.

enum color { red, green, blue };
color c = red;

// to serialize
archive << c;    // Removed cast

// to deserialize
int i;
archive >> i;
c = (color)i;    // Removed switch

Andere Tipps

Enum Klasse ist ein C ++ 0x Merkmal wird nicht in C ++ 03.

  

In Standard-C ++, Aufzählungen sind nicht typsicher. Sie sind effektiv ganze Zahlen, auch wenn die Aufzählungstypen unterscheiden. Dies ermöglicht den Vergleich zwischen zwei ENUM-Werten verschiedenen Aufzählungstypen. Die einzige Sicherheit, die C ++ 03 bereitstellt, ist, dass eine ganze Zahl oder ein Wert von einer Aufzählungstyp nicht implizit auf einem anderen Aufzählungstyp konvertiert. Zusätzlich kann der zugrunde liegende Integraltyp, die Größe der ganzen Zahl kann nicht explizit angegeben werden; es ist die Umsetzung definiert. Schließlich Aufzählungswerte werden an den umschließenden Umfang scoped. Somit ist es nicht möglich, dass zwei getrennte Aufzählungen passende Mitgliedernamen zu haben.   C ++ 0x wird eine besondere Klassifizierung der Aufzählung ermöglichen, die keines dieser Themen hat. Dies drückt die Enum Klassendeklaration mit

Beispiele (aus dem Wikipedia-Artikel):

enum Enum1;                   //Illegal in C++ and C++0x; no size is explicitly specified.
enum Enum2 : unsigned int;    //Legal in C++0x.
enum class Enum3;             //Legal in C++0x, because enum class declarations have a default type of "int".
enum class Enum4: unsigned int; //Legal C++0x.
enum Enum2 : unsigned short;  //Illegal in C++0x, because Enum2 was previously declared with a different type.

Wie für die Serialisierung Teil (was ich denke, war nicht Teil der ursprünglichen Frage), ziehe ich eine Hilfsklasse zu erstellen, die ENUM-Elemente in ihr String übersetzt äquivalent (und zurück), wie die Namen sind in der Regel stabiler als die ganzzahlige Werte sie vertreten, als enum Elemente sein können (und manchmal sind) neu geordnet, ohne den Code Verhalten zu ändern.

ich beschlossen, eine neue Antwort zu schaffen, weil meine alte so chaotisch war. Auf jeden Fall wollen nur etwas über C ++ 11 sagen, wo Sie den zugrunde liegenden Typ einer Aufzählung bekommen kann mit dieser:

std::underlying_type_t<E>

Und im Interesse der Zinsen, Idee der Überladungsauflösung. Aber bitte Namen verwenden, um die Auszählung zu speichern, wie @lothar vorgeschlagen.

Die Überlast Auflösung ergibt sich aus der Tatsache, dass es eine Förderung aus einer Aufzählung existieren zu dem ersten von int, unsigned int, lang, unsigned long, der alle Werte seiner zugrunde liegenden Typ darstellen kann. Eine Umwandlung in jedem anderen Integer-Typ ist niedriger gewählt und Überladungsauflösung wird es nicht vorziehen.

char (& f(int) )[1];
char (& f(unsigned int) )[2];

char (& f(long) )[3];
char (& f(unsigned long) )[4];

char const* names[] = { 
    "int", "unsigned int", 
    "long", "unsigned long"
};

enum a { A = INT_MIN };
enum b { B = UINT_MAX };
enum c { C = LONG_MIN };
enum d { D = ULONG_MAX };

template<typename T> void print_underlying() {
    std::cout << names[sizeof(f(T()))-1] << std::endl;
}

int main() { 
    print_underlying<a>();
    print_underlying<b>();
    print_underlying<c>();
    print_underlying<d>();
}

Und es druckt diese eine hier:

int
unsigned int
int
unsigned int

Es ist nicht von besonderem Interesse für diese Serialisierung Problem (da die Größe der serialisierten Daten nicht konstanter Breite, und dies kann zu Problemen führen, wenn die Aufzählung und die ihr zugrunde liegender Typ geändert wird), aber es ist in der Regel interessant, herauszufinden, eine Art, die Gesamtheit einer Aufzählungs speichern. Cheers!

#include <type_traits>

enum a { bla1, bla2 };
typedef typename std::underlying_type<a>::type underlying_type;

if (std::is_same<underlying_type, int>::value)
  std::cout << "It's an int!" << endl;
else if (std::is_same<underlying_type, unsigned int>::value)
  std::cout << "It's an uint!" << endl;

In Bezug auf enum class color: Ist der C ++ / CLI (C ++) oder zukünftige C ++ 0x-Code

Für die Serialisierung, könnten Sie die Aufzählungsgröße mit sizeof(color) erhalten zu wissen, wie viele Bytes zu kopieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top