Pergunta

Eu tenho tentado ler um pouco do C ++ padrão para descobrir o trabalho de como enum. Na verdade, há mais lá do que eu pensava.

Para uma enumeração escopo, é claro que o tipo subjacente é int a menos que especificado de outro modo com uma cláusula enum-base (que pode ser qualquer tipo integrante).

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

Para enumerações sem escopo, parece que o tipo subjacente pode ser qualquer tipo integral que irá trabalhar e que não será maior do que um int, a menos que ele precisa ser.

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

Uma vez que o tipo subjacente de enumarations sem escopo não são padronizados, o que é a melhor maneira de lidar com a serialização de instâncias de um? Até agora, eu tenho a conversão para int ao escrever, em seguida, a serialização em um int e definir minha variável enum em um interruptor ao ler, mas parece um pouco desajeitado. Existe uma maneira melhor?

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;
}
Foi útil?

Solução

Eu não tenho ler qualquer C ++ 0x coisas assim que eu não poderia comentar sobre isso.

Como para a serialização, você não precisa o interruptor ao ler a parte de trás enum in - apenas lançá-lo para o tipo enum

.

No entanto, eu não lançam ao escrever para o fluxo. Isso ocorre porque muitas vezes eu gosto de escrever um operador << para o enum para que eu possa pegar maus valores sendo escrito, ou então eu posso decidir escrever uma corda em seu lugar.

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

Outras dicas

classe enum é um C ++ 0x recurso, não está presente em C ++ 03.

Em C ++ padrão, enumerações não são de tipo seguro. Eles são efetivamente inteiros, mesmo quando os tipos de enumeração são distintos. Isto permite a comparação entre os dois valores de enumeração de diferentes tipos de enumeração. A única segurança que C ++ 03 fornece é que um inteiro ou um valor de um tipo de enumeração não implicitamente converter para outro tipo enum. Além disso, o tipo integral subjacente, o tamanho do número inteiro, pode não ser que explicitamente especificado; é definido pela implementação. Por último, enumeração valores são escopo para o escopo de inclusão. Assim, não é possível para duas enumerações separados para ter nomes de membros correspondentes. C ++ 0x permitirá uma classificação especial de enumeração que não tem nenhuma dessas questões. Isto é expresso usando a declaração de classe enum

Exemplos (a partir do artigo 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.

Quanto à parte de serialização (que eu acho que não era parte da pergunta original), eu prefiro criar uma classe auxiliar que traduz enum itens no seu equivalente string (e volta), como os nomes são geralmente mais estável do que o valores inteiros que representam, como itens de enumeração pode ser (e às vezes são) reordenadas sem alterar o comportamento do código.

Eu decidi criar uma nova resposta, porque o meu velho estava tão confuso. De qualquer forma só quero dizer algo sobre C ++ 11, onde você pode obter o tipo subjacente de uma enumeração usando este:

std::underlying_type_t<E>

E por uma questão de interesse, a idéia de resolução de sobrecarga. Mas, por favor use nomes para armazenar a enumeração, como proposto por @lothar.

A resolução de sobrecarga decorre do fato de que existem uma promoção de uma enumeração para o primeiro de int, sem assinatura int, longo, longo não assinado que pode representar todos os valores de seu tipo subjacente. A conversão para qualquer outro tipo inteiro é menor classificado e resolução de sobrecarga não vai preferi-lo.

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

E ele imprime este aqui:

int
unsigned int
int
unsigned int

Não é de particular interesse para este problema de serialização (uma vez que o tamanho dos dados serializados não é de largura constante, e isso pode causar problemas quando a enumeração e seu tipo subjacente é alterado), mas geralmente é interessante para descobrir um tipo de armazenamento do conjunto de uma enumeração. Felicidades!

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

Como a enum class color:? É este o C ++ / CLI (C ++ .NET) ou futuro C ++ 0x código

Para a serialização, você pode obter o tamanho do enum com sizeof(color) saber quantos bytes copiar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top