4

理想的には、次の例が機能することを望みますが、C++ で実装できないものもあると思います。

{
  typedef StrongEnum<Red=0, Green=1, Blue=2> Color; // not a C++ syntax
  Color c = Color::Red;  // static const 
  Color d;  //error: default constructor is private 
  Color d = c;
  Color e = Color::OfInt(5); // ifdef DEBUG - Runtime error: Enum out of range 

  int sum = 0;

  // I do have these macros, but separate for each enum - FOREACH_COLOR(c)
  FOREACH_ENUM (Color c) { 
    sum += c.ToInt ();
  }

  ArrayMap<Color, string> map;  // Internally this is const size array, possible
  map [Color::Red] = "red";     // because Color have static const Limit = 3 inisde. 

  // Advanced: EnumPair does bitpacking.
  // currently I implement it manually for every pair of Enum's I need.
  typedef EnumPair <door=Color, window=Color> ColorPair; // I guess I can't get this, can I?
  ColorPair pair (door = Color::Red, window = Color::Green); // I guess I can't give the labels here or one line above, can I?
  Color w = pair.window;
  Color w = pair.window ();
}

私はそれらをたくさん使っており、現在はそれぞれを最初から書いています。完全な一般的な解決策は夢であることを認識しているため、部分的な解決策は歓迎します。誰かがライブラリやコードジェネレータを作成したのではないでしょうか?

更新 1:

これこの質問は関連しています。それらで解決できる問題を調査しています。

4

2 に答える 2

2

これは私が理解したことです:

#include <cstdio>
#include <string>
#include <map>

namespace Color
{
    typedef enum
    {
        Red = 0,
        Green = 1,
        Blue = 2
    } Color;

    Color colors[] = {Red, Green, Blue}; // same order as above,
                                         //to preserve index.

    //int colors_len = sizeof(colors)/sizeof(Color);
    // (if you want to check for valid values)

    static inline Color OfInt(int value)
    {
        // if(value >= colors_len) do error thing;
        return colors[value];
    }
}

int main()
{
    Color::Color c = Color::Red;

    printf("%d,", c);

    c = Color::OfInt(1);

    printf("%d,", c);

    c = Color::Blue;

    printf("%d\n", c);

    std::map<Color::Color, std::string> map;

    map[Color::Red] = "red";

    return 0;
}

少なくともそれはあなたが望む振る舞いのいくつかを持っています。これにはあなたが必要とするものが欠けていますか?

g ++ 4.3.3でコンパイルされ、問題なく動作するようです。

列挙型を別のスコープに配置するために名前空間を使用しました。(赤が取られないようにするためなど)多分あなたはそれをあなたが使うことができる何かに分解することができますか?:)

その名前空間の外側にColor::Colorが必要な場合は、次のようにすることができます。

typedef Color::Color ColorEnum;

しかし、残念ながら、Colorという名前は名前空間によって占められています。

于 2009-10-28T11:34:11.600 に答える
0

また、C++ での列挙型の実際の実装も嫌いです。

  • 整数型への自動変換
  • 値のチェックなし: 格納するために選択された整数型に値が収まるかどうかを確認するために、緩い範囲チェックが実行されます。
  • シリアル化: int としてシリアル化するのは面倒です > 使用しなくなった場合でも古い値を保持する必要があり、最後にのみ新しい値を追加する必要があります
  • 反復はできません。演算子を再定義する必要があります

私は自分のテンプレートをロールバックして自動化を試みましたが、現時点では完全に満足できるものではありません(特に、列挙型ごとにテンプレートの特殊化が必要なため、クラス/構造体にネストされた列挙型には使用できないためです:/)

とにかく、私が使用したアイデアは次のとおりです。

  • 値とその「シリアル化値」を格納するための静的マップ (私の場合は、スペースをあまり重視せず、読みやすさを優先するため、単純な文字列です)
  • マップ内のイテレータを保持するだけのラップするクラス。'end' は初期化されていない/無効な値を表します。

今のところ、「真の」列挙型を使用しましたが、あなたが言ったことから、静的インスタンスを持つことを考えるかもしれません...列挙型ライターにさらに別の負担をかけますが...

于 2009-10-27T13:55:24.767 に答える