以一般方式选择有效的随机枚举值

时间:2014-08-18 06:36:32

标签: c++ c++11 random enums

假设我们有一个枚举类型E

enum class E : underlying_type_of_E {
 v1 = uE1,
 v2 = uE2,
   //...
 vN = uEN
};

typedef typename std::underlying_type<E>::type uE;

通常,并非uE的所有值都是E的有效值,因为我们可以选择它们之间的关系。是否有一种创建随机,有效(在定义中命名,而不是可分配),E的值的一般方法? 例如,这不起作用:

std::mt19937 m;
std::uniform_int_distribution<uE> randomUE(0, std::numeric_limits<uE>::max());

E e = static_cast<E>( randomUE(m) );

,因为:

  1. 值范围可能不是从0开始
  2. 值范围可能不会以std :: numeric_limits :: max()
  3. 结尾
  4. 值范围可能根本不是范围 - 我们可以从uE中选择E的离散值,例如{1,3,62,272}。
  5. 鉴于所有枚举值在编译时都是已知的,我无法想象为什么这会以任何方式危险或容易出错。

    至于为什么我想要这样的事情的背景 - 我正在研究一种使用模板化基因存储的遗传算法。现在,我使用枚举作为染色体并将它们存储在std::vector<bool>中,并根据需要转换为std::vector<enumT>。这种方法的问题是以给定概率翻转随机位的突变。这可能会导致问题,因为它会产生无效的染色体,这些染色体是未命名的枚举值。

1 个答案:

答案 0 :(得分:2)

如果您准备使用预处理器宏来创建enum类型及其中的某些元数据,则可以执行此操作,但这只是轻微的麻烦:

  • 调用可变参数宏:

    ENUM(E,
         v1 = uE1,
         v2 = uE2,
         // ...
         vN = uEN);
    
  • 创建一个模板化的类Incrementing,默认情况下,连续变量由递增的static成员初始化,但可以从任何基础类型中分配(例如int )。

    static Incrementing<E, Underlying> __VA_ARGS__; \
    
  • 使用上面的值初始化具有Incrementing值的数组(需要operator Underlying() const成员)。

    static const Underlying values[] = { __VA_ARGS__ }; \
    

然后values[]数组包含命名的枚举值....

我在几年前写过这个概念的完全矫枉过正的版本here,但我建议只是从头开始给出你的简单要求。