Domanda

Ho cercato di leggere un po 'dello standard C ++ per capire il lavoro come di enum. C'è in realtà più là che ho inizialmente pensato.

Per un censimento scope, è chiaro che il tipo sottostante è int se non diversamente specificato, con una clausola enum-base (che può essere qualsiasi tipo integrale).

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

Per enumerazioni senza ambito, sembra che il tipo sottostante può essere qualsiasi tipo integrale che funzionerà e che non sarà più grande di un int, solo se deve essere.

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

Dato che il tipo sottostante di enumarations senza ambito non sono standardizzati, qual è il modo migliore di trattare con serializzazione istanze di uno? Finora, sono stato la conversione in enum quando si scrive poi la serializzazione in un <=> e impostando il mio <=> variabile in uno switch durante la lettura, ma sembra un po 'goffo. C'è un modo migliore?

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;
}
È stato utile?

Soluzione

Non ho letto alcun roba C ++ 0x quindi non ho potuto commentare su questo.

Per quanto riguarda la serializzazione, non è necessario l'interruttore quando la lettura del enum indietro nel -. Appena gettato al tipo enum

Tuttavia, non mi gettai quando si scrive al flusso. Questo perché spesso mi piace scrivere un operatore << per l'enumerazione in modo da poter prendere cattivi valori scritti, o posso quindi decidere di scrivere una stringa invece.

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

Altri suggerimenti

classe enum è un C ++ 0x caratteristica, non è presente in C ++ 03.

  

In serie C ++, enumerazioni non sono type-safe. Sono numeri interi in modo efficace, anche quando i tipi di enumerazione sono distinti. Questo permette il confronto tra due valori enum di diversi tipi di enumerazione. L'unica sicurezza che C ++ 03 prevede che è un numero intero o un valore di un tipo enum non converte implicitamente ad un altro tipo enum. Inoltre, il tipo integrale sottostante, la dimensione del numero intero, non può essere esplicitamente specificato; è definita attuazione. Infine, valori di enumerazione vengono ambiti all'ambito racchiude. Pertanto, non è possibile per due enumerazioni separati per avere i nomi dei membri corrispondenti.   C ++ 0x consentirà una speciale classifica di enumerazione che ha nessuno di questi problemi. Ciò è espresso utilizzando la dichiarazione della classe enum

Gli esempi (dalla voce di 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.

Per quanto riguarda la parte di serializzazione (che credo non era parte della domanda originale), preferisco creare una classe di supporto che traduce gli elementi enum nella loro stringa equivalente (e ritorno), come i nomi sono di solito più stabile rispetto al valori interi che rappresentano, come elementi enum possono essere (e talvolta sono) riordinato senza modificare il comportamento del codice.

ho deciso di creare una nuova risposta, perché il mio vecchio era così disordinato. In ogni caso voglio solo dire qualcosa su C ++ 11, dove è possibile ottenere il tipo di fondo di un'enumerazione utilizzando questa:

std::underlying_type_t<E>

E per il bene di interesse, l'idea la risoluzione di sovraccarico. Ma per favore utilizzare nomi per memorizzare l'enumerazione, come proposto da @lothar.

La risoluzione di sovraccarico deriva dal fatto che esistono una promozione da un'enumerazione al primo int, unsigned int, long, unsigned long che può rappresentare tutti i valori del proprio tipo sottostante. Una conversione a qualsiasi altro tipo integer è bassa classifica e la risoluzione di sovraccarico non preferirà esso.

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 la stampa questa qui:

int
unsigned int
int
unsigned int

Non è di particolare interesse per questo problema di serializzazione (poiché la dimensione dei dati serializzati non è di larghezza costante, e questo può causare problemi quando l'enumerazione e il suo tipo sottostante viene modificato), ma è generalmente interessante capire un tipo memorizzare l'intera un'enumerazione. 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;

Per quanto riguarda enum class color:? È questo il C ++ / CLI (C ++ .NET) o futuri codice C ++ 0x

Per la serializzazione, si potrebbe ottenere la dimensione della enum con sizeof(color) sapere quanti byte da copiare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top