【问题标题】:Is there C++ library to create strong Enums?是否有 C++ 库来创建强大的枚举?
【发布时间】:2010-12-10 10:40:22
【问题描述】:

理想情况下,我希望以下示例能够正常工作,但我想其中一些示例无法在 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:

Thisthis 问题是相关的。我正在研究他们可以解决哪些问题。

【问题讨论】:

  • 但是partial并不意味着实现上面的Color类。这意味着部分泛型 Enum 以避免一遍又一遍地重新实现相同的方法。
  • 您在寻找安全标签吗? artima.com/cppsource/safelabels.html
  • 是的,我知道 C++0x 中的枚举类,但它本身并不能解决我的问题。

标签: c++ enums c++11


【解决方案1】:

这是我想出来的:

#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 被命名空间占用了。

【讨论】:

  • 我认为他想要一些可以自动化这个过程的东西(例如:颜色、季节等)。
  • 我没有以可以扩展的方式使用宏。我会使用上面的解决方案,手动编写它们。如果他需要,他可以用 python 或其他可以快速创建该文件的脚本编写脚本,但我不确定这是否值得。
【解决方案2】:

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

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

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

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

  • 用于存储值及其“序列化值”的静态映射(在我的例子中是一个简单的字符串,因为我不太重视空间并且更喜欢可读性)
  • 要包装的类,它只是在映射中保存一个迭代器,“end”表示一个未初始化/无效的值。

目前我使用了“真正的”枚举,但从你所说的来看,我可能会想到有静态实例......尽管它给枚举作者带来了另一个负担......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    相关资源
    最近更新 更多