I just noticed that you can not use standard math operators on an enum such as ++ or +=
So what is the best way to iterate through all of the values in a C++ enum?
The typical way is as follows:
enum Foo {
One,
Two,
Three,
Last
};
for ( int fooInt = One; fooInt != Last; fooInt++ )
{
Foo foo = static_cast<Foo>(fooInt);
// ...
}
Please note, the enum Last
is meant to be skipped by the iteration. Utilizing this "fake" Last
enum, you don't have to update your terminating condition in the for loop to the last "real" enum each time you want to add a new enum.
If you want to add more enums later, just add them before Last. The loop in this example will still work.
Of course, this breaks down if the enum values are specified:
enum Foo {
One = 1,
Two = 9,
Three = 4,
Last
};
This illustrates that an enum is not really meant to iterate through. The typical way to deal with an enum is to use it in a switch statement.
switch ( foo )
{
case One:
// ..
break;
case Two: // intentional fall-through
case Three:
// ..
break;
case Four:
// ..
break;
default:
assert( ! "Invalid Foo enum value" );
break;
}
If you really want to enumerate, stuff the enum values in a vector and iterate over that. This will properly deal with the specified enum values as well.
#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;
}
With c++11, there actually is an alternative: writing a simple templatized custom iterator.
let's assume your enum is
enum class foo {
one,
two,
three
};
This generic code will do the trick, quite efficiently - place in a generic header, it'll serve you for any enum you may need to iterate over:
#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; }
};
You'll need to specialize it
typedef Iterator<foo, foo::one, foo::three> fooIterator;
And then you can iterate using range-for
for (foo i : fooIterator() ) { //notice the parentheses!
do_stuff(i);
}
The assumption that you don't have gaps in your enum is still true; there is no assumption on the number of bits actually needed to store the enum value (thanks to std::underlying_type)
I often do it like that
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))
{}
or if not successive, but with regular step (e.g. bit flags)
enum EAnimalCaps
{
E_None = 0,
E_First = 0x1,
E_CanFly = E_First,
E_CanWalk = 0x2
E_CanSwim = 0x4,
E_Last
}
class MyAnimal
{
EAnimalCaps m_Caps;
}
class Frog
{
Frog() :
m_Caps(EAnimalCaps(E_CanWalk | E_CanSwim))
{}
}
for (EAnimalCaps= E_First; i < E_Last; i = EAnimalCaps(i << 1))
{}
Something that hasn't been covered in the other answers = if you're using strongly typed C++11 enums, you cannot use ++
or + int
on them. In that case, a bit of a messier solution is required:
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)
}
You can try and define the following macro:
#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))
Now you can use it:
enum Count { zero, one, two, three };
for_range (Count, c, zero, three)
{
cout << "forward: " << c << endl;
}
It can be used to iterate backwards and forwards through unsigned, integers, enums and chars:
for_range (unsigned, i, 10,0)
{
cout << "backwards i: " << i << endl;
}
for_range (char, c, 'z','a')
{
cout << c << endl;
}
Despite its awkward definition it is optimized very well. I looked at disassembler in VC++. The code is extremely efficient. Don't be put off but the three for statements: the compiler will produce only one loop after optimization! You can even define enclosed loops:
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;
}
You obviously cannot iterate through enumerated types with gaps.
Assuming that enum is numbered sequentially is error prone. Moreover, you may want to iterate over selected enumerators only. If that subset is small, looping over it explicitly might be an elegant choice:
enum Item { Man, Wolf, Goat, Cabbage }; // or enum class
for (auto item : {Wolf, Goat, Cabbage}) { // or Item::Wolf, ...
// ...
}
Here's another solution which only works for contiguous enums. It gives the expected iteration, except for ugliness in the increment, which is where it belongs, since that's what's broken in 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))
{
// ...
}
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);
}
A constexpr std::array
can iterate even non-sequential enums without the array being instantiated by the compiler. This depends on things like the compiler's optimization heuristics and whether you take the array's address.
In my experiments, I found that g++
9.1 with -O3
will optimize away the above array if there are 2 non-sequential values or quite a few sequential values (I tested up to 6). But it only does this if you have an if
statement. (I tried a statement that compared an integer value greater than all the elements in a sequential array and it inlined the iteration despite none being excluded, but when I left out the if statement, the values were put in memory.) It also inlined 5 values from a non-sequential enum in [one case|https://godbolt.org/z/XuGtoc]. I suspect this odd behavior is due to deep heuristics having to do with caches and branch prediction.
Here is a link to a simple test iteration on godbolt that demonstrates the array does not always get instantiated.
The price of this technique is writing the enum elements twice and keeping the two lists in sync.
If you do not like to pollute you enum with a final COUNT item (because maybe if you also use the enum in a switch then then the compiler will warn you of a missing case COUNT:), you can do this:
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);
}
There is already discussion about std::initializer_list (C++11) in the comments. I am mentioning example to iterate over the enum.
or std::initializer_list and a simpler syntax:
enum E {
E1 = 4,
E2 = 8,
// ..
En
};
constexpr std::initializer_list<E> all_E = {E1, E2, /*..*/ En};
and then
for (auto e : all_E) {
// Do job with e
}
Reference Link
In Bjarne Stroustrup's C++ programming language book, you can read that he's proposing to overload the operator++
for your specific enum
. enum
are user-defined types and overloading operator exists in the language for these specific situations.
You'll be able to code the following:
#include <iostream>
enum class Colors{red, green, blue};
Colors& operator++(Colors &c, int)
{
switch(c)
{
case Colors::red:
return c=Colors::green;
case Colors::green:
return c=Colors::blue;
case Colors::blue:
return c=Colors::red; // managing overflow
default:
throw std::exception(); // or do anything else to manage the error...
}
}
int main()
{
Colors c = Colors::red;
// casting in int just for convenience of output.
std::cout << (int)c++ << std::endl;
std::cout << (int)c++ << std::endl;
std::cout << (int)c++ << std::endl;
std::cout << (int)c++ << std::endl;
std::cout << (int)c++ << std::endl;
return 0;
}
test code: http://cpp.sh/357gb
Mind that I'm using enum class
. Code works fine with enum
also. But I prefer enum class
since they are strong typed and can prevent us to make mistake at compile time.
For MS compilers:
#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);
}
Note: this is a lot less code than the simple templatized custom iterator answer.
You can get this to work with GCC by using typeof
instead of decltype
, but I don't have that compiler handy at the moment to make sure it compiles.
If you knew that the enum values were sequential, for example the Qt:Key enum, you could:
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);
}
}
It works as expected.
Extending @Eponymous's answer: It's great, but doesn't provide a general syntax. Here's what I came up with:
// Common/EnumTools.h
#pragma once
#include <array>
namespace Common {
// Here we forward-declare metafunction for mapping enums to their values.
// Since C++<23 doesn't have reflection, you have to populate it yourself :-(
// Usage: After declaring enum class E, add this overload in the namespace of E:
// inline constexpr auto allValuesArray(const E&, Commob::EnumAllValuesTag) { return std::array{E::foo, E::bar}; }
// Then `AllValues<NS::E>` will call `allValuesArray(NS::E{}, EnumAllValuesTag)` which will resolve
// by ADL.
// Just be sure to keep it sync'd with your enum!
// Here's what you want to use in, e.g., loops: "for (auto val : Common::AllValues<MyEnum>) {"
struct EnumAllValuesTag {}; // So your allValuesArray function is clearly associated with this header.
template <typename Enum>
static inline constexpr auto AllValues = allValuesArray(Enum{}, EnumAllValuesTag{});
// ^ Just "constexpr auto" or "constexpr std::array<Enum, allValuesArray(Enum{}, EnumAllValuesTag{}).size()>" didn't work on all compilers I'm using, but this did.
} // namespace Common
then in your namespace:
#include "Common/EnumTools.h"
namespace MyNamespace {
enum class MyEnum {
foo,
bar = 4,
baz = 42,
};
// Making this not have to be in the `Common` namespace took some thinking,
// but is a critical feature since otherwise there's no hope in keeping it sync'd with the enum.
inline constexpr auto allValuesArray(const MyEnum&, Common::EnumAllValuesTag) {
return std::array{ MyEnum::foo, MyEnum::bar, MyEnum::baz };
}
} // namespace MyNamespace
then wherever you need to use it:
for (const auto& e : Common::AllValues<MyNamespace::MyEnum>) { ... }
so even if you've typedef'd:
namespace YourNS {
using E = MyNamespace::MyEnum;
} // namespace YourNS
for (const auto& e : Common::AllValues<YourNS::E>) { ... }
I can't think of anything much better, short of the actual language feature everyone looking at this page want.
Future work:
constexpr
function (and so a metafunction) that filters Common::AllValues<E>
to provide a Common::AllDistinctValues<E>
for the case of enums with repeated numerical values like enum { foo = 0, bar = 0 };
.switch
-covers-all-enum
-values to write allValuesArray
such that it errors if the enum has added a value.Upsides: enums can have any values you like in any order you like and it's still easy to iterate over them. Names and values are defined once, in the first #define.
Downsides: if you use this at work, you need a whole paragraph to explain it to your coworkers. And, it's annoying to have to declare memory to give your loop something to iterate over, but I don't know of a workaround that doesn't confine you to enums with adjacent values (and if the enum will always have adjacent values, the enum might not be buying you all that much anyway.)
//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
The trick of declaring a list with an undefined macro wrapper, and then defining the wrapper differently in various situations, has a lot of applications other than this one.
Just make an array of ints and loop over the array, but make the last element say -1 and use it for exit condition.
If enum is:
enum MyEnumType{Hay=12,Grass=42,Beer=39};
then create array:
int Array[] = {Hay,Grass,Beer,-1};
for (int h = 0; Array[h] != -1; h++){
doStuff( (MyEnumType) Array[h] );
}
This does not break down no matter the ints in the representation as long as -1 check does not collide with one of the elements of course.
int
may not be big enough! ([C++03: 7.2/5]
) – Lightness Races in Orbitoperator++
on enums; however, so you can dofor(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++)
. Note you have to cast0
toEnum_E
because C++ forbids assignment operators on enums. – weberc2