and*_*ykx 247
典型的方法如下:
enum Foo {
One,
Two,
Three,
Last
};
for ( int fooInt = One; fooInt != Last; fooInt++ )
{
Foo foo = static_cast<Foo>(fooInt);
// ...
}
Run Code Online (Sandbox Code Playgroud)
当然,如果指定了枚举值,这会分解:
enum Foo {
One = 1,
Two = 9,
Three = 4,
Last
};
Run Code Online (Sandbox Code Playgroud)
这说明枚举并不是真正意义上的迭代.处理枚举的典型方法是在switch语句中使用它.
switch ( foo )
{
case One:
// ..
break;
case Two: // intentional fall-through
case Three:
// ..
break;
case Four:
// ..
break;
default:
assert( ! "Invalid Foo enum value" );
break;
}
Run Code Online (Sandbox Code Playgroud)
如果你真的想要枚举,将枚举值填入向量中并迭代它.这也将适当地处理指定的枚举值.
The*_*ign 43
#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;
}
Run Code Online (Sandbox Code Playgroud)
Joã*_*sto 18
如果你的枚举以0开头,则增量始终为1.
enum enumType
{
A = 0,
B,
C,
enumTypeEnd
};
for(int i=0; i<enumTypeEnd; i++)
{
enumType eCurrent = (enumType) i;
}
Run Code Online (Sandbox Code Playgroud)
如果不是,我想唯一的原因就是创造类似的东西
vector<enumType> vEnums;
Run Code Online (Sandbox Code Playgroud)
添加项目,并使用普通迭代器....
小智 17
使用c ++ 11,实际上还有另一种选择:编写一个简单的模板化自定义迭代器.
让我们假设你的枚举是
enum class foo {
one,
two,
three
};
Run Code Online (Sandbox Code Playgroud)
这个通用代码可以非常高效地完成这一操作 - 放置在通用头文件中,它可以为您可能需要迭代的任何枚举提供服务:
#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; }
};
Run Code Online (Sandbox Code Playgroud)
你需要专门化它
typedef Iterator<foo, foo::one, foo::three> fooIterator;
Run Code Online (Sandbox Code Playgroud)
然后你可以使用range-for进行迭代
for (foo i : fooIterator() ) { //notice the parentheses!
do_stuff(i);
}
Run Code Online (Sandbox Code Playgroud)
你的枚举中没有间隙的假设仍然是正确的; 对存储枚举值实际需要的位数没有假设(感谢std :: underlying_type)
Enz*_*ojz 14
这些解决方案太复杂了,我喜欢这样:
enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};
const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };
for (NodePosition pos : NodePositionVector) {
...
}
Run Code Online (Sandbox Code Playgroud)
小智 13
假设枚举按顺序编号很容易出错。此外,您可能只想迭代选定的枚举器。如果该子集很小,则显式循环它可能是一个优雅的选择:
enum Item { Man, Wolf, Goat, Cabbage }; // or enum class
for (auto item : {Wolf, Goat, Cabbage}) { // or Item::Wolf, ...
// ...
}
Run Code Online (Sandbox Code Playgroud)
将变量转换为 anint&
可以让您在保持类型可读的同时进行增量。
#include <iostream>
enum MyEnum
{
ONE,
TWO,
THREE,
FOUR,
};
int main()
{
for (MyEnum v = MyEnum::ONE; v <= MyEnum::FOUR; ++(int&)v)
{
std::cout<<v<<std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
0
1
2
3
Run Code Online (Sandbox Code Playgroud)
我经常这样做
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))
{}
Run Code Online (Sandbox Code Playgroud)
或者如果不是连续的,但是使用常规步骤(例如位标志)
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))
{}
Run Code Online (Sandbox Code Playgroud)
enum class A {
a0=0, a3=3, a4=4
};
constexpr std::array<A, 3> ALL_A {A::a0, A::a3, A::a4}; // constexpr is important here
for(A a: ALL_A) {
if(a==A::a0 || a==A::a4) std::cout << static_cast<int>(a);
}
Run Code Online (Sandbox Code Playgroud)
Aconstexpr std::array
甚至可以迭代非顺序枚举,而无需编译器实例化数组。这取决于编译器的优化启发式以及是否采用数组的地址等因素。
在我的实验中,我发现如果有 2 个非连续值或相当多的连续值(我测试了最多 6 个),g++
9.1将优化掉上面的数组。-O3
但只有当你有声明时它才会这样做if
。(我尝试了一个语句,该语句比较大于顺序数组中所有元素的整数值,并且它内联了迭代,尽管没有排除任何元素,但是当我省略 if 语句时,这些值被放入内存中。)它还内联了 5 [一种情况| 中非顺序枚举的值] https://godbolt.org/z/XuGtoc]。我怀疑这种奇怪的行为是由于与缓存和分支预测有关的深度启发式造成的。
这是一个关于 godbolt 的简单测试迭代的链接,它演示了数组并不总是被实例化。
这种技术的代价是将枚举元素写入两次并保持两个列表同步。
您可以尝试定义以下宏:
#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))
Run Code Online (Sandbox Code Playgroud)
现在你可以使用它:
enum Count { zero, one, two, three };
for_range (Count, c, zero, three)
{
cout << "forward: " << c << endl;
}
Run Code Online (Sandbox Code Playgroud)
它可用于通过无符号,整数,枚举和字符向后和向前迭代:
for_range (unsigned, i, 10,0)
{
cout << "backwards i: " << i << endl;
}
for_range (char, c, 'z','a')
{
cout << c << endl;
}
Run Code Online (Sandbox Code Playgroud)
尽管定义很尴尬,但它的优化得非常好.我在VC++中查看了反汇编程序.代码非常有效.不要推迟但是三个for语句:编译器在优化后只会产生一个循环!您甚至可以定义封闭的循环:
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;
}
Run Code Online (Sandbox Code Playgroud)
你显然无法通过间隙迭代枚举类型.
其他答案中未涉及的内容=如果您使用的是强类型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<myenumtype>(static_cast<int>(myenum) + 1)) {
do_whatever(myenum)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
286428 次 |
最近记录: |