我只是注意到你不能在枚举上使用标准数学运算符,如++或+ =
那么迭代C++枚举中所有值的最佳方法是什么?
典型的方法如下:
enum Foo { One, Two, Three, Last }; for ( int fooInt = One; fooInt != Last; fooInt++ ) { Foo foo = static_cast(fooInt); // ... }
当然,如果指定了枚举值,这会分解:
enum Foo { One = 1, Two = 9, Three = 4, Last };
这说明枚举并不是真正意义上的迭代.处理枚举的典型方法是在switch语句中使用它.
switch ( foo ) { case One: // .. break; case Two: // intentional fall-through case Three: // .. break; case Four: // .. break; default: assert( ! "Invalid Foo enum value" ); break; }
如果你真的想要枚举,将枚举值填入向量中并迭代它.这也将适当地处理指定的枚举值.
#include#include 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; }
如果你的枚举以0开头,则增量始终为1.
enum enumType { A = 0, B, C, enumTypeEnd }; for(int i=0; i如果不是,我想唯一的原因就是创造类似的东西
vectorvEnums; 添加项目,并使用普通迭代器....
4> 小智..:使用c ++ 11,实际上还有另一种选择:编写一个简单的模板化自定义迭代器.
让我们假设你的枚举是
enum class foo { one, two, three };这个通用代码可以非常高效地完成这一操作 - 放置在通用头文件中,它可以为您可能需要迭代的任何枚举提供服务:
#includetemplate < typename C, C beginVal, C endVal> class Iterator { typedef typename std::underlying_type ::type val_t; int val; public: Iterator(const C & f) : val(static_cast (f)) {} Iterator() : val(static_cast (beginVal)) {} Iterator operator++() { ++val; return *this; } C operator*() { return static_cast (val); } Iterator begin() { return *this; } //default ctor is good Iterator end() { static const Iterator endIter=++Iterator(endVal); // cache it return endIter; } bool operator!=(const Iterator& i) { return val != i.val; } }; 你需要专门化它
typedef IteratorfooIterator; 然后你可以使用range-for进行迭代
for (foo i : fooIterator() ) { //notice the parentheses! do_stuff(i); }你的枚举中没有间隙的假设仍然是正确的; 对存储枚举值实际需要的位数没有假设(感谢std :: underlying_type)
@lepe这就像说`std :: vector`不是通用的,因为`std :: vector <foo>`绑定到`foo`。
哦,我看到了这个问题-`foo operator *(){...`应该是`C operator *(){...`。
5> Enzojz..:这些解决方案太复杂了,我喜欢这样:
enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3}; const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary }; for (NodePosition pos : NodePositionVector) { ... }
我希望这是因为条目需要在两个地方维护.
@thegreatjedi自C ++ 11起,您甚至可以更加简单:for(auto pos:NodePositionVector){..}
6> Corey Trager..:你不能用枚举.也许enum不是最适合你的情况.
一个常见的约定是将最后一个枚举值命名为MAX,并使用它来控制使用int的循环.
7> Niki..:我经常这样做
enum EMyEnum { E_First, E_Orange = E_First, E_Green, E_White, E_Blue, E_Last } for (EMyEnum i = E_First; i < E_Last; i = EMyEnum(i + 1)) {}或者如果不是连续的,但是使用常规步骤(例如位标志)
enum EAnimal { E_First, E_None = E_First, E_CanFly = 0x1, E_CanWalk = 0x2 E_CanSwim = 0x4, E_Last } for (EAnimali = E_First; i < E_Last; i = EAnimal(i << 1)) {}
8> Mikhail Seme..:您可以尝试定义以下宏:
#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++中查看了反汇编程序.代码非常有效.不要推迟但是三个for语句:编译器在优化后只会产生一个循环!您甚至可以定义封闭的循环:
unsigned p[4][5]; for_range (Count, i, zero,three) for_range(unsigned int, j, 4, 0) { p[i][j] = static_cast(i)+j; } 你显然无法通过间隙迭代枚举类型.
`_A1`不是允许的名称,它是带有以下大写字母的前导下划线.
9> Riot..:其他答案中未涉及的内容=如果您使用的是强类型C++ 11枚举,则不能使用
++
或+ int
使用它们.在这种情况下,需要一些更麻烦的解决方案:enum class myenumtype { MYENUM_FIRST, MYENUM_OTHER, MYENUM_LAST } for(myenumtype myenum = myenumtype::MYENUM_FIRST; myenum != myenumtype::MYENUM_LAST; myenum = static_cast(static_cast (myenum) + 1)) { do_whatever(myenum) }
...但是C++ 11引入了基于其他答案的范围.:-)