質問

私はどのように列挙型の仕事を把握するためにC ++標準のビットを読み取るためにしようとしてきました。より多くのそこ私が当初考えていたよりも実際にあります。

スコープの列挙については、それはそうでなければ列挙ベースの句(それは、任意の整数型であることができる)で指定しない限り、根本的なタイプがintあることは明らかだ。

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

、スコープ外列挙型の場合、それは動作しますし、それがあることが必要である場合を除き、それは、int型よりも大きくならないことを任意の整数タイプにすることができ、基礎となるタイプのように思える。

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

、スコープ外enumarationsの基になる型が標準化されていませんので、1のシリアライズインスタンスに対処する最良の方法は何ですか?これまでのところ、私はintにシリアライズし、読み取り時にスイッチで私int変数を設定し、次に書くときenumに変換するされてきたが、それは少し不格好と思われます。より良い方法はありますか?

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;
}
役に立ちましたか?

解決

私はそれについてはコメントできなかったので、

私は、任意のC ++ 0xのものを読んでいない。

後ろに列挙型を読み込むときに

シリアル化するとして、あなたはスイッチを必要としません - 。ちょうど列挙型にキャスト

ストリームに書き込むときに、

しかし、私はキャストしないでください。私は頻繁に私が書き込まれている不正な値をキャッチすることができ、または私は、代わりに文字列を書き出すことを決定することができるように列挙型のための演算子を<<書くことが好きなので、これがあります。

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

他のヒント

の列挙型クラス C ++ 0xの機能、それはC ++ 03の中には存在しない。

  

標準C ++では、列挙型は、タイプセーフではありません。彼らは、列挙型が異なっている場合でも、効果的に整数です。これは、異なる列挙型の2つの列挙値との比較を可能にします。 C ++ 03が提供する唯一の安全性は、整数または1つの列挙型の値を別の列挙型に暗黙的に変換しないことです。また、基本となる整数型、整数のサイズは、明示的に指定することができません。それは、実装定義されています。最後に、列挙値を囲むスコープにスコープされています。二つの別々の列挙型が一致するメンバー名を持っているためこのように、それは不可能です。   C ++ 0xのは、これらの問題のどれを持っていない列挙の特別な分類が可能になります。これは、列挙クラス宣言を使用して表現される

(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.

、私は名前が通常よりも安定しているとして、(背中と)同等のその文字列に列挙アイテムを変換するヘルパークラスを作成することを好む(私は元の質問の一部ではなかったと思う)シリアライズ部分については列挙項目があること(時にはある)ことができるようにそれらが表す整数値は、コードの挙動を変更することなく、並べ替えます。

私は私の古いが、とても厄介だったので、新しい答えを作成することにしました。とにかくちょうどあなたが使用して列挙の基になる型を取得することができるものについてのC ++ 11を、言いたいこの1:

std::underlying_type_t<E>

と関心のため、オーバーロードの解決のアイデアについて。しかし@lotharによって提案されているように、列挙を保存するために名前を使用してください。

オーバーロード解決は、列挙からint型、unsigned int型、その基礎となるタイプのすべての値を表すことができる長い、unsigned long型の最初の1つの振興が存在するという事実から生じます。任意の他の整数型への変換が低くランクされ、オーバーロード解決がそれを好むことはありません。

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

そして、それはここで、このいずれかを出力します:

int
unsigned int
int
unsigned int

(シリアライズデータのサイズが一定の幅ではなく、これは時に列挙し、その基になる型が変更された問題を引き起こす可能性がありますので)それは、このシリアル化の問題に特に関心がないのですが、把握することが一般的に興味深いです列挙の全体を保存するタイプ。乾杯!

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

enum class colorするには:?このC ++ / CLI(C ++。NET)または将来のC ++ 0xのコードです。

直列化のために、あなたはコピーするバイト数を知ることがsizeof(color)でenumのサイズを得ることができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top