有没有用于创建强类型枚举的C++库?

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: 这些问题(链接)(链接)是相关的。我正在调查哪些问题可以用它们解决。

但是“partial”并不意味着要在上面实现Color类。它意味着部分通用枚举,以避免反复重新实现相同的方法。 - Łukasz Lew
1
您正在寻找安全标签吗?请访问http://www.artima.com/cppsource/safelabels.html。 - Dominic Rodger
是的,我知道C++0x中的枚举类,但它本身并不能解决我的问题。 - Łukasz Lew
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编译,并且似乎工作正常。

我将命名空间用于将枚举放在不同的范围内。(所以不会出现Red被占用等情况。)也许你可以将其分解为可用的部分? :)

如果你想在该命名空间之外使用Color :: Color,则可以执行以下操作:

typedef Color::Color ColorEnum;

但是名字Color被名称空间占用了。

我认为他想要一些可以自动化这个过程的东西(例如:对于颜色、季节等)。 - n1ckp
我从未使用过可以扩展到那种程度的宏。我会选择使用上面的解决方案,手动编写它们。如果他需要的话,他可以编写一个Python脚本或其他东西,快速创建该文件,但我不确定是否值得这样做。 - pbos

0

我也讨厌C++中枚举的实际实现。

  • 自动转换为整数类型
  • 没有值检查:仅执行宽松的范围检查以查看该值是否适合选择存储它的整数类型
  • 序列化:作为int序列化是痛苦的>即使不再使用旧值,您也必须保留它们,并且只能在末尾添加新值
  • 无法迭代,需要重新定义运算符

最终我自己编写了一个模板来尝试自动化,但目前还不完全令人满意(特别是因为它需要为每个枚举进行模板专业化,因此无法用于嵌套在类/结构中的枚举 :/)

无论如何,我使用的想法是:

  • 静态映射以存储值及其“序列化值”(在我的情况下,这是一个简单的字符串,因为我不太关心空间,更喜欢可读性)
  • 包装的类,仅在映射中持有一个迭代器,“end”表示未初始化/无效值。

目前我使用了“真正”的枚举,但根据您的说法,我可以考虑使用静态实例...尽管这会给枚举编写者带来另一个负担...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接