以一般方式选择有效的随机枚举值 [英] Selecting a valid random enum value in a general way

查看:196
本文介绍了以一般方式选择有效的随机枚举值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say we have an enumerated type 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?
这将,例如不工作:

In general, not all values of uE are valid values of E, because we can choose the relationship between them. Is there a general way of creating random, valid (named in definition, not assignable), values of E? This, for example would not work:

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,64,272}。

假设所有的枚举值在编译时都是已知的,我不能想象这是为什么会危险或容易出错的原因。

Given that all of the enumerated values are known at compile-time, I cannot imagine a reason why would this be in any way dangerous, or error-prone.

至于为什么我想要这样的事情的上下文 - 我正在研究使用模板化基因存储的遗传算法。现在,我使用枚举作为染色体并将它们存储在 std :: vector< bool> ,它被转换为 std :: vector< enumT& / code>按需。这种方法的问题是以给定概率翻转随机位的突变。

As for a context of why I want such a thing - I'm working on a genetic algorithm that uses templated gene storage. For now, I use enums as chromosomes and store them in std::vector<bool> which is converted into std::vector<enumT> on demand. The problem with this approach is mutation that flips random bits with given probability. That can cause problems, as it can produce invalid chromosomes that are unnamed enum values.

推荐答案

这可能会导致问题,因为它可以产生无效的染色体是未命名的枚举值。准备使用预处理器宏来创建 enum 类型和一些关于它的元数据,但它是一个小麻烦:

You can do this if you're prepared to use a preprocessor macro to create both the enum type and some meta-data about it, but it's a minor hassle:


  • 调用可变参数宏:

  • Invoke a variadic macro:

ENUM(E,
     v1 = uE1,
     v2 = uE2,
     // ...
     vN = uEN);


  • 创建模板类增量其中连续变量由默认情况下递增的 static 成员初始化,但可以从任何您的底层类型被分配(例如 int )。

  • Create a templated class Incrementing where successive variables are initialised by an incrementing static member by default, but can be assigned to from whatever your underlying type is (e.g. int).

    static Incrementing<E, Underlying> __VA_ARGS__; \
    


  • 使用上面的值来初始化数组增加值(需要一个运算符Underlying()const 成员)。

  • Use the values above to initialise a array with the Incrementing values (which need an operator Underlying() const member).

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


  • values [] array然后包含命名的枚举值....

    The values[] array then contains the named enumeration values....

    这个概念的一个总的overkill版本我写几年前这里,但我建议从头开始,只要你的简单要求。

    There's a total overkill version of this concept I wrote years ago here, but I'd recommend just starting from scratch given your simple requirements.

    这篇关于以一般方式选择有效的随机枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆