c++ - 如何循环访问枚举 ?

我刚刚注意到,不能在枚举上使用标准的数学运算符,比如 或 =

迭代C enum值的最佳方法是什么?

时间:

典型的方法如下:


enum Foo {
 One,
 Two,
 Three,
 Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
 Foo foo = static_cast<Foo>(fooInt);
 // ...
}

当然,如果指定了enum值,则会中断:


enum Foo {
 One = 1,
 Two = 9,
 Three = 4,
 Last
};

这表明一个enum并不真正意味着,处理enum的典型方法是在switch语句中使用它。


switch ( foo )
{
 case One:
 // ..
 break;
 case Two: // intentional fall-through
 case Three:
 // ..
 break;
 case Four:
 // ..
 break;
 default:
 assert( !"Invalid Foo enum value" );
 break;
}

如果你真的想枚举,在vector中填充enum值,然后迭代,这将正确处理指定的enum值。

许多方法之一:枚举时不够: C++的枚举类。

如果你想要更多的东西封装,尝试这种方法从詹姆斯 Kanze 。

如果enum以0开头,并且增量始终为1.


enum enumType 
{ 
 A = 0,
 B,
 C,
 enumTypeEnd
};

for(int i=0; i<enumTypeEnd; i++)
{
 enumType eCurrent = (enumType) i; 
}


vector<enumType> vEnums;

添加项,并使用正常迭代器。

一个常见的约定是命名enum最后的值,比如MAX,然后使用int来控制循环。

可以尝试定义以下宏:


#define for_range(_type, _param, _A1, _B1) for (bool _ok = true; _ok;)
for (_type _start = _A1, _finish = _B1; _ok;)
 for (int _step = 2*(((int)_finish)>(int)_start)-1;_ok;)
 for (_type _param = _start; _ok ; 
 (_param != _finish ? 
 _param = static_cast<_type>(((int)_param)+_step) : _ok = false))

现在你可以使用它:


enum Count { zero, one, two, three }; 

 for_range (Count, c, zero, three)
 {
 cout <<"forward:" << c << endl;
 }

它可用于循环访问无符号,整数,枚举和字符:


for_range (unsigned, i, 10,0)
{
 cout <<"backwards i:" << i << endl;
}


for_range (char, c, 'z','a')
{
 cout << c << endl;
}

尽管它的定义很笨拙,但它的优化非常好,我查看了VC++的反汇编器,代码非常有效,优化后,编译器将只生成一个循环!你甚至可以定义封闭循环:


unsigned p[4][5];

for_range (Count, i, zero,three)
 for_range(unsigned int, j, 4, 0)
 { 
 p[i][j] = static_cast<unsigned>(i)+j;
 }

也可以重载枚举类型的递增/递减运算符。

这些解决方案太复杂了,我喜欢:


enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};

const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };

for (NodePosition pos : NodePositionVector) {
...
}


#include <iostream>
#include <algorithm>

namespace MyEnum
{
 enum Type
 {
 a = 100,
 b = 220,
 c = -1
 };

 static const Type All[] = { a, b, c };
}

void fun( const MyEnum::Type e )
{
 std::cout << e << std::endl;
}

int main()
{
 // all
 for ( const auto e : MyEnum::All )
 fun( e );

 // some
 for ( const auto e : { MyEnum::a, MyEnum::b } )
 fun( e );

 // all
 std::for_each( std::begin( MyEnum::All ), std::end( MyEnum::All ), fun );

 return 0;
}

如果使用的是强类型C 11 enum,就不能对它们使用 或 int,在这种情况下,需要一些更复杂的解决方案:


enum class myenumtype {
 MYENUM_FIRST,
 MYENUM_OTHER,
 MYENUM_LAST
}

for(myenumtype myenum = myenumtype::MYENUM_FIRST;
 myenum != myenumtype::MYENUM_LAST;
 myenum = static_cast<myenumtype>(static_cast<int>(myenum) + 1)) {

 do_whatever(myenum)

}

C++ 没有自省,所以你不能在run-time处决定这种事情。

...