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

问题描述 投票:0回答:7

我有一些 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,但它看起来很难看,我从未见过有人在代码中这样做。是否有用于迭代枚举的任何众所周知的范例,或者我只需要修复枚举值的顺序? (让我们假装,我真的有一些很棒的理由来改变枚举值的顺序)...

c++ enums iteration
7个回答
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--()


4
投票

不,没有办法这样做,因为不能保证有人没有写过这样的代码:

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

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。)


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

这样做你可以授予第一个和最后一个永远不会改变顺序


0
投票

如果你不使用任何赋值,枚举保证是从 0 作为第一个开始的顺序。 那些。

你能做的最好的事情就是让它们在你的枚举定义中保持你想要的顺序,并用 for 循环循环它们。


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;

这显然是错误的。

© www.soinside.com 2019 - 2024. All rights reserved.