迭代枚举值是否有任何众所周知的范例?

时间:2009-08-18 07:55:46

标签: c++ enums iteration

我有一些C ++代码,其中声明了以下枚举:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma,
   Some_Total
};
int array[Some_Total];

Alpha,Beta和Gamma的值是连续的,我很乐意使用以下循环来迭代它们:

for ( int someNo = (int)Some_Alpha; someNo < (int)Some_Total; ++someNo ) {}

这个循环没问题,直到我决定改变枚举中声明的顺序,比如说,使Beta成为第一个值,而Alpha - 第二个。这使循环标头无效,因为现在我必须从Beta迭代到Total。 那么,迭代枚举的最佳实践是什么?我希望迭代所有值,而不是每次都更改循环标题。我能想到一个解决方案:

enum Some 
{
   Some_Start = -1,
   Some_Alpha,
   ...
   Some_Total
};
int array[Some_Total];

并从(Start + 1)迭代到Total,但它看起来很难看,我从未见过有人在代码中这样做。是否有任何众所周知的范例来迭代枚举,或者我只需要修复枚举值的顺序? (让我们假装,我真的有一些改变枚举值顺序的绝佳理由)......

7 个答案:

答案 0 :(得分:13)

您可以为operator++()定义enum。这具有以下优点:它使用标准增量运算符的众所周知的范例。 :)

根据您的枚举是否连续,您可以将其视为int或使用开关:

Some& operator++(Some& obj)
{
# if YOUR_ENUMS_ARE_CONTIGUOUS
  int i = obj;
  if( ++i > Some_Total ) i = Some_Alpha;
  return obj = static_cast<Some>(i);
# else 
  switch(obj)
  {
    case Some_Alpha : obj = Some_Beta;  break;
    case Some_Beta  : obj = Some_Gamma; break;
    case Some_Gamma : obj = Some_Total; break;
    case Some_Total : obj = Some_Alpha; break;
    default: assert(false); // changed enum but forgot to change operator
  }
  return obj;
# endif
}

请注意,如果定义了operator++(),用户可能也会期望operator--()

答案 1 :(得分:4)

不,没有办法这样做,因为无法保证有人没有编写如下代码:

enum Some 
{
   Some_Alpha = 0,
   Some_Beta,
   Some_Gamma = 42,
   Some_Delta, 
  Some_Total
};

答案 2 :(得分:3)

您可以使用article查看此source code,了解如何使用静态类成员实现此功能。

答案 3 :(得分:1)

在C ++ 11中(可能更早),您可以使用以下hack来使Some可迭代:

Some operator++(Some& s) {
    return s = (Some )(std::underlying_type<Some>::type(x) + 1); 
}
Some operator*(Some s) {
    return s;
} 
Some begin(Some s) {
    return Some_Alpha;

Some end(Some s) {
    return Some_Gamma;
}

int main() { 
    // the parenthesis here instantiate the enum
    for(const auto& s : Some()) { 
        // etc. etc.
    }
    return 0;
}

(这个答案是从here无耻地改编而来的。)

答案 4 :(得分:0)

enum Some
{
   Some_first_ = 0,
   Some_Alpha = Some_first_,
....
   Some_last_
};

这样做可以先授予&amp;最后从不改变订单

答案 5 :(得分:0)

如果您不使用任何分配,则保证枚举以0开头顺序排列。 thers。

您可以做的最好的事情是在枚举定义中按顺序保留它们,并使用for循环遍历它们。

答案 6 :(得分:0)

我将所有枚举放在他们自己的命名空间中。例如:

namespace Foo {
enum Enum {
    First=0, // must be sequential
    Second,
    Third,
    End // must be last
};
}

在代码中:

for (int i=Foo::First; i!=Foo::End; i++) {
// do stuff
}

这是因为C ++允许这样的东西(未在编译器中测试):

enum Foo {
Alpha = 1
};

enum Bar {
Beta = 2
};

Foo foo = Beta;

这显然是错误的。