我如何迭代枚举?
我只注意到你不能在一个像++或+ =这样的枚举上使用标准的math运算符
那么迭代C ++枚举中所有值的最好方法是什么?
典型的方法如下:
enum Foo { One, Two, Three, Last }; for ( int fooInt = One; fooInt != Last; fooInt++ ) { Foo foo = static_cast<Foo>(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; }
如果你真的想枚举,将枚举值填充到一个向量中并遍历它。 这将正确处理指定的枚举值。
许多方法之一: 当枚举只是不够:枚举类为C + + 。
而且,如果你想要更多封装的东西,可以尝试James Kanze的方法。
如果你的枚举以0开始,增量总是1。
enum enumType { A = 0, B, C, enumTypeEnd }; for(int i=0; i<enumTypeEnd; i++) { enumType eCurrent = (enumType) i; }
如果不是,我想唯一的原因是创build一个像
vector<enumType> vEnums;
添加项目,并使用正常的迭代器….
#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,实际上有一个select:编写一个简单的模板化的自定义迭代器。
让我们假设你的枚举是
enum class foo { one, two, three };
这个generics代码将会非常有效地实现这个技巧 – 放置在一个通用头文件中,它将为您提供任何需要迭代的枚举:
#include <type_traits> template < typename C, C beginVal, C endVal> class Iterator { typedef typename std::underlying_type<C>::type val_t; int val; public: Iterator(const C & f) : val(static_cast<val_t>(f)) {} Iterator() : val(static_cast<val_t>(beginVal)) {} Iterator operator++() { ++val; return *this; } C operator*() { return static_cast<C>(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 Iterator<foo, foo::one, foo::three> fooIterator;
然后你可以迭代使用range-for
for (foo i : fooIterator() ) { //notice the parenteses! do_stuff(i); }
你在枚举中没有空白的假设依然如此。 没有关于实际需要存储枚举值的位数的假设(感谢std :: underlying_type)
你不能用枚举。 也许一个枚举不是最适合你的情况。
一个常见的惯例是将最后一个枚举值命名为MAX,并使用它来控制使用int的循环。
这些解决scheme太复杂了,我这样做:
enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3}; const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary }; for (NodePosition pos : NodePositionVector) { ... }
您可以尝试并定义下面的macros:
#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; }
尽pipe它的定义很尴尬,但它的优化效果非常好。 我在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; }
你显然不能遍历枚举types的差距。
其他答案中未涉及的东西=如果使用强types的C ++ 11枚举,则不能在其上使用++
或+ int
。 在这种情况下,需要一些更复杂的解决scheme:
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) }
您也可以为您的枚举types重载递增/递减运算符。
如果你不喜欢污染你枚举最后的COUNT项(因为也许如果你也在开关中使用枚举然后编译器会警告你一个遗漏的案件COUNT :),你可以这样做:
enum Colour {Red, Green, Blue}; const Colour LastColour = Blue; Colour co(0); while (true) { // do stuff with co // ... if (co == LastColour) break; co = Colour(co+1); }
对于MS编译器:
#define inc_enum(i) ((decltype(i)) ((int)i + 1)) enum enumtype { one, two, three, count}; for(enumtype i = one; i < count; i = inc_enum(i)) { dostuff(i); }
注意:这比简单的模板化自定义迭代器的答案less了很多代码。
你可以通过使用typeof
而不是decltype
来使用GCC,但是目前我没有这个编译器,以确保它能够编译。
C ++没有反省,所以你不能在运行时确定这种事情。
如果您知道枚举值是连续的,例如Qt:Key枚举,您可以:
Qt::Key shortcut_key = Qt::Key_0; for (int idx = 0; etc...) { .... if (shortcut_key <= Qt::Key_9) { fileMenu->addAction("abc", this, SLOT(onNewTab()), QKeySequence(Qt::CTRL + shortcut_key)); shortcut_key = (Qt::Key) (shortcut_key + 1); } }
它按预期工作。
我经常这样做
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 EMyEnum { E_First, E_None = E_First, E_Green = 0x1, E_White = 0x2 E_Blue = 0x4, E_Last } for (EMyEnum i = E_First; i < E_Last; i = EMyEnum(i << 1)) {}