以一般方式选择有效的随机枚举值 [英] Selecting a valid random enum value in a general way
问题描述
假设我们有一个枚举类型 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) );
因为:
- 值范围不能从0开始
- 值范围不能以std :: numeric_limits :: max()
- 不是一个范围 - 我们可以从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屋!