我只是注意到不能在枚举上使用标准数学运算符,如++或+=。
那么,在c++枚举中遍历所有值的最佳方法是什么?
我只是注意到不能在枚举上使用标准数学运算符,如++或+=。
那么,在c++枚举中遍历所有值的最佳方法是什么?
当前回答
#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;
}
其他回答
枚举就不行。也许枚举不是最适合您的情况。
一个常见的约定是将最后一个枚举值命名为MAX,并使用它来控制一个int类型的循环。
下面是另一种只适用于连续枚举的解决方案。它给出了期望的迭代,除了增量中的丑陋,这是它的归属,因为这是c++中破坏的地方。
enum Bar {
One = 1,
Two,
Three,
End_Bar // Marker for end of enum;
};
for (Bar foo = One; foo < End_Bar; foo = Bar(foo + 1))
{
// ...
}
在评论中已经有关于std::initializer_list (c++ 11)的讨论。 我提到example是为了遍历枚举。
或者std::initializer_list和一个更简单的语法:
enum E {
E1 = 4,
E2 = 8,
// ..
En
};
constexpr std::initializer_list<E> all_E = {E1, E2, /*..*/ En};
然后
for (auto e : all_E) {
// Do job with e
}
参考链接
使用lambda,我发现这是遍历枚举的最佳(现代)方式。 这大大提高了抽象性。 甚至可以使它成为模板,所以它适用于任何枚举。 这段代码不会给您带来clang(-tidy)问题。
#include <functional>
/// @brief Loop over all enum values where the last enum value is the invalid one
void forEachAction(std::function<void(Enum)> &&doThis) {
for (int value = 0; value = static_cast<int>(Enum::LastValue); ++value ) {
doThis(static_cast<Enum>(value ));
}
}
...
forEachAction([this](Enum value) {
... // what you want to execute for every enum
});
优点:枚举可以有你喜欢的任意顺序的任何值,并且仍然很容易迭代它们。 名称和值只定义一次,在第一个#define中。
缺点:如果你在工作中使用这个短语,你需要用一整段话来向你的同事解释。而且,必须声明内存来给你的循环提供迭代的东西是很烦人的,但我不知道有什么解决办法不限制你使用相邻值的枚举(如果枚举总是有相邻值,enum可能不会给你买那么多)。
//create a, b, c, d as 0, 5, 6, 7
#define LIST x(a) x(b,=5) x(c) x(d)
#define x(n, ...) n __VA_ARGS__,
enum MyEnum {LIST}; //define the enum
#undef x //needed
#define x(n,...) n ,
MyEnum myWalkableEnum[] {LIST}; //define an iterable list of enum values
#undef x //neatness
int main()
{
std::cout << d;
for (auto z : myWalkableEnum)
std::cout << z;
}
//outputs 70567
使用未定义的宏包装器声明一个列表,然后在各种情况下以不同的方式定义包装器的技巧,除了这个应用程序之外,还有许多应用程序。