【问题标题】:Sequence of enumerators at compile time编译时的枚举数序列
【发布时间】:2013-06-19 15:32:37
【问题描述】:

给定一个 C++11 枚举类,是否有一些模板或其他构造在编译时迭代所有枚举器的集合?可以定义一个模板,例如用该枚举类型的所有可能值初始化一个数组?

【问题讨论】:

  • 您可以使用以template <class T, T...> class Enum 开头的可变模板类和参数包来滚动您自己的类枚举类型,但它并不是非常漂亮。 C++ 需要更好的反思,并且有一个工作组试图解决这个问题。

标签: c++ c++11 enums enum-class


【解决方案1】:

另一种技术是使用预处理器。

#define ITERATE_MY_ENUM(_) \
  _(A,) \
  _(B, =3) \
  _(C,) \
  _(D, =10)

enum MyEnum {
  #define DEFINE_ENUM_VALUE(key, value) key value,

  ITERATE_MY_ENUM(DEFINE_ENUM_VALUE)

  #undef DEFINE_ENUM_VALUE
};

void foo() {
  MyEnum arr[] = {
    #define IN_ARRAY_VALUE(key, value) key,

    ITERATE_MY_ENUM(IN_ARRAY_VALUE)

    #udnef IN_ARRAY_VALUE
  };
}

有些人可能认为它丑陋,但它仍然保留代码DRY

【讨论】:

  • 我曾考虑过为此使用预处理器,但我的方法会涉及更多,使用许多 boost 宏。您的解决方案看起来更容易阅读并且更轻量级。应该可以以value 包含= 的方式修改代码,这样如果您想要某些键的自动增量行为,您可以将值留空。显然,数组应该根据键来指定。你想编辑你的代码吗?
【解决方案2】:

不,没有这样的事情。另请注意,枚举类型不仅可以合法地保存枚举数的值,还可以将它们的任何组合或组合在一起(模糊地说)。

您可能可以使用一些简单的代码生成器来解决问题。

反映评论: Here 很好地总结了 C++11 中关于类枚举的变化。这些解决了隐式转换、对底层类型的控制、名称范围,但基本性质没有改变。枚举器仍然只是接近文字的东西,没有可发现的连接。你所要求的将需要某种反思,AFAIK 它还没有出现。

【讨论】:

  • 我不确定答案的 OR 部分是否正确。事实上,我很确定情况正好相反。枚举类型的对象只能持有一个枚举数,持有其他任何东西都是未定义的行为。代码enum E { ONE=1, TWO=2 }; E e = ONE | TWO; switch (e) { case ONE: cout << "1"; break; case TWO: cout << "2"; break; default: cout << "other"; }; 可能根本不会打印任何内容(即允许编译器优化掉“默认”分支,因为“e”的所有有效值都有自己的大小写。
  • 3 是该枚举的完全有效值
  • 我知道这种值的组合对旧的enum 枚举器有效,但一直希望enum class 可以摆脱它。在任何情况下,列出所有明确命名的枚举数都可以。只计算枚举数就可以了:只要没有人明确分配值,就可以使用强制类型转换将底层类型的实例转换为有效值。
  • 我不确定如何将值 3 赋予包含值 12 的 C++11 类枚举。
  • 我使用的生成器(我自己编写的)将生成迭代器,如果任何枚举常量具有显式值(紧跟在名称后面的=)。同样,它不会生成 &| 函数,除非它们都有明确的值。
猜你喜欢
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多