在循环中使用枚举和值一致性 [英] Using enum in loops and value consistency

查看:126
本文介绍了在循环中使用枚举和值一致性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C ++的强类型功能的狂热粉丝,我最喜欢的是在处理有限的数据集时使用枚举。

I'm a big fan of C++'s strong-typing features and what I like the most is to use enumerations while dealing with limited sets of data.

但是枚举缺少一些有用的功能,例如运算符:

But enumerations lack some useful features, for example operators:

enum class Hex : int
{
    n00, n01, n02, n03,
    n04, n05, n06, n07,
    n08, n09, n10, n11,
    n12, n13, n14, n15
};

for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Oops! no 'operator ++'
{ /* ... */ }



以消除运算符在同一范围上创建一个自由运算符的缺乏:

Is easy to get rid of the lack of operators creating a free operator on the same scope:

Hex &operator ++(Hex &h)
{
    int r = static_cast<int>(Hex);
    h = static_cast<Hex>(r + 1);
    return h;
}

for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Now the '++h' works!
{
    std::cout << std::dec << int(h) << ": "
              << std::hex << int(h) << '\n';
}

但这种方法比解决方案更讨厌,因为它可以打破枚举的值限制:应用 ++ h ,而 h 等于 Hex :: n15 将设置h为值16,它是 Hex 范围的值,而 h 仍然是 Hex !类型,这个问题在其他枚举中更为明显:

But this approach is more a nuisance than a solution, because it can break the value limitation of the enumeration: applying ++h while h equals to Hex::n15 will set h to he value 16, wich is out of the Hex scope of values while h is still of the type Hex!, This problem is more evident in other enumerations:

enum class Prime : int
{
    n00 = 2,   n01 = 3,   n02 = 5,   n03 = 7,
    n04 = 11,  n05 = 13,  n06 = 17,  n07 = 19,
    n08 = 23,  n09 = 29,  n10 = 31,  n11 = 37,
    n12 = 41,  n13 = 43,  n14 = 47,  n15 = 53
};

Prime &operator ++(Prime &p)
{
    // How to implement this?! will I need a lookup table?
    return p;
}

这个问题对我来说是一个惊喜;我押注将不正确的值存储到枚举值将抛出异常。所以,现在我想知道是否有一个优雅的方式来处理这个枚举的弱点,我想实现的目标是:

This problem was a surprise for me; I was betting that storing an incorrect value into an enumeration value will throw an exception. So, for now I was wondering if there's an elegant way to deal with this enumeration's weaknesses, the goals I want to achieve are:


  • Find

  • 确保操作之间的枚举数据一致性。

其他问题:


  • 当枚举数据获得的值超出其可能的值时,是否有理由不抛出异常?

  • 有一种方法可以推断与枚举类关联的类型, int 在枚举类型 Hex Prime

  • Is there a reason for not throwing an exception when an enumeration data gets a value that is out of its possible values?
  • There is a way to deduce the type associated with an enumeration class?, the int type in the enumerations Hex and Prime.

推荐答案

如你所见,C ++中的枚举不是枚举类型,
,复合(或更混合)。当你定义一个
枚举时,你事实上定义了两件事:

As you've noticed, enum in C++ is not an enumerated type, but something more complex (or more mixed). When you define an enum, you define in fact two things:


  1. 一个整数类型,其法定范围足以包含
    或所有枚举值。 (技术上:范围
    2 ^ n-1 ,其中 n

具有新定义类型的一系列命名常量。

A series of named constants having the newly defined type.

(如果
明确指定了底层类型,我不知道对范围会发生什么。)

(I'm not sure what happens with regards to the range if you explicitly specify an underlying type.)

例如,假设您的枚举Prime ,合法值为
0 ... 64),即使所有这些
值没有名称。 (至少如果你没有具体说明
说它应该是 int 。)

Given your enum Prime, for example, the legal values would be all integers in the range [0...64), even if all of these values don't have a name. (At least if you didn't specifically say that it should be an int.)

可以实现枚举的迭代器而不用
初始化器;我有一个程序,生成必要的
代码。但它的工作原理是将值保存在一个整数类型
中,它足够大以包含最大值加一。我的
机器生成 ++ 在这样一个枚举上的实现
assert 增加超过结束。 (注意
你的第一个例子将需要迭代 h 一个超出
最后一个值:我的各种运算符的实现不
allow这是为什么我使用迭代器。)

It's possible to implement an iterator for enums without initializers; I have a program which generates the necessary code. But it works by maintaining the value in an integral type which is large enough to contain the maximum value plus one. My machine generated implementations of ++ on such an enum will assert if you try to increment beyond the end. (Note that your first example would require iterating h one beyond the last value: my implementation of the various operators does not allow this, which is why I use an iterator.)

至于为什么C ++支持扩展范围: enum 经常使用
定义位掩码:

As to why C++ supports the extended range: enum are often used to define bit masks:

enum X
{
    a = 0x01,
    b = 0x02,
    c = 0x04,
    all = a | b | c,
    none = 0
};

X operator|( X lhs, X rhs )
{
    return X((int)lhs | (int)rhs);
}
//  similarly, &, |= and &=, and maybe ~

有人可能会认为这种使用会更好地由
a类处理,但是使用 enum 是无处不在的。

One could argue that this use would be better handled by a class, but the use of enum for it is ubiquitous.

(FWIW:我的代码生成器不会生成 ++ -
迭代器,如果任何枚举值具有明确的
定义值,并且不会生成 | & ; 等,除非所有的
的值都有明确定义的值。)

(FWIW: my code generator will not generate the ++, -- and the iterators if any of the enum values has an explicitly defined value, and will not generate |, & etc. unless all of the values have explicitly defined values.)

至于为什么没有错误,当你转换一些值在
之外的法律范围(例如100,对于 X ,上面)只是保持
与继承自C的一般哲学:要是
快比是正确的。进行额外范围检查将
需要额外的运行时成本。

As to why there is no error when you convert some value outside the legal range (e.g. 100, for X, above) is simply in keeping with the general philosophy inherited from C: it's better to be fast than to be correct. Doing extra range checking would entail additional runtime cost.

最后关于你的最后一个例子:我不认为这是
a现实使用枚举。这里正确的解决方案是
int [] 。虽然C ++ 枚举是一个混合的品种,我会
只使用它作为一个真正的枚举类型,或位掩码(和
只位掩码,因为它是如此广泛建立的
成语)。

Finally with regards to your last example: I don't see this as a realistic use of enum. The correct solution here is an int[]. While the C++ enum is rather a mixed breed, I would only use it as a real enumerated type, or for bit masks (and only for bit masks because it is such a widely established idiom).

这篇关于在循环中使用枚举和值一致性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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