Question

J'ai essayé de lire un peu de la norme C ++ pour comprendre le travail de la façon dont ENUM. Il y a en fait plus là que je pensais à l'origine.

Pour une énumération scope, il est clair que le type sous-jacent est int, sauf indication contraire avec une disposition à base de enum (il peut être de tout type intégral).

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

Pour énumérations non délimité, il semble que le type sous-jacent peut être tout type intégral qui fonctionne et que ce ne sera pas plus grand qu'un int, à moins qu'il doit être.

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

Étant donné que le type sous-jacent de enumarations non délimité ne sont pas standardisés, ce qui est la meilleure façon de traiter les cas sérialisation d'un? Jusqu'à présent, j'ai à la conversion lors de l'écriture mise en enum sérialisation dans un <=> puis ma variable dans un <=> interrupteur lors de la lecture, mais il semble un peu maladroit. Y at-il une meilleure façon?

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;
}
Était-ce utile?

La solution

Je n'ai pas lu toute substance C ++ 0x donc je ne pouvais pas commenter.

En ce qui concerne la sérialisation, vous n'avez pas besoin du commutateur lors de la lecture du ENUM en arrière -. Juste jeter au type enum

Cependant, je ne rejetez pas lors de l'écriture au courant. Ceci est parce que j'aime souvent d'écrire un opérateur << pour la ENUM pour que je puisse attraper de mauvaises valeurs en cours d'écriture, ou je peux décider d'écrire une chaîne à la place.

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

Autres conseils

classe enum est un C ++ 0x caractéristique, il est pas présent dans 03 C ++.

  

Dans la norme C ++, énumérations ne sont pas typées. Ils sont des entiers efficacement, même lorsque les types d'énumération sont distincts. Cela permet la comparaison entre deux valeurs ENUM de différents types d'énumération. La seule sécurité que 03 C ++ fournit est qu'un entier ou une valeur d'un type enum ne convertit pas implicitement à un autre type de ENUM. En outre, le type intégré sous-jacent, la taille de l'entier, ne peut pas être spécifié explicitement; il est défini par l'implémentation. Enfin, les valeurs d'énumération sont étendus à la portée englobante. Ainsi, il est impossible pour deux énumérations séparés d'avoir des noms de membres correspondant.   C ++ 0x permettra un classement spécial de l'énumération qui n'a aucune de ces questions. Ceci est exprimé en utilisant la déclaration de classe enum

Exemples (de l'article wikipedia):

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.

En ce qui concerne la partie de sérialisation (qui je pense ne faisait pas partie de la question initiale), je préfère créer une classe d'aide qui se traduit par des éléments de ENUM dans leur chaîne équivalente (et retour), les noms sont généralement plus stables que la des valeurs entières qu'ils représentent, en tant qu'éléments de enum peuvent être (et sont parfois) réordonnés sans modifier le comportement de code.

J'ai décidé de créer une nouvelle réponse parce que mon vieux était tellement en désordre. Quoi qu'il en soit je veux juste dire quelque chose à propos de C ++ 11, où vous pouvez obtenir le type sous-jacent d'une énumération en utilisant celui-ci:

std::underlying_type_t<E>

Et pour des raisons d'intérêt, l'idée de la résolution de surcharge. Mais s'il vous plaît utiliser des noms pour stocker l'énumération, tel que proposé par @lothar.

La résolution de surcharge découle du fait qu'il existe une promotion d'une énumération à la première int, unsigned int, long, unsigned long qui peut représenter toutes les valeurs de son type sous-jacent. Une conversion à un autre type entier est classé plus bas et la résolution de surcharge ne préférer.

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

Et il imprime celui-ci ici:

int
unsigned int
int
unsigned int

Il est pas d'intérêt particulier à ce problème de sérialisation (puisque la taille des données sérialisées n'est pas de largeur constante, et cela peut causer des problèmes lors de l'énumération et son type sous-jacent est modifié), mais il est généralement intéressant de comprendre un type stockage de l'ensemble d'une énumération. Vive!

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

Quant à enum class color: Est-ce C ++ / CLI (C ++ .NET) ou futur code C ++ 0x

Pour sérialisation, vous pouvez obtenir la taille de l'ENUM avec savoir sizeof(color) nombre d'octets à copier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top