412

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?

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Adam
  • 25,966
  • 23
  • 76
  • 87
  • Linked items have some interesting responses. – Tony Jun 13 '13 at 01:27
  • 1
    These answers don't seem to cover the problem that `int` may not be big enough! (`[C++03: 7.2/5]`) – Lightness Races in Orbit Jun 21 '13 at 10:03
  • Interestingly, you can define `operator++` on enums; however, so you can do `for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++)`. Note you have to cast `0` to `Enum_E` because C++ forbids assignment operators on enums. – weberc2 Jun 25 '14 at 22:52
  • If there was a compile time operator, similar to the way sizeof works, that could emit a std::initializer_list literal comprised of the values of the enum, we would have a solution and would not involve any runtime overhead. – jbruni Dec 13 '17 at 23:56
  • 2
    One of many approaches: [When enum Just Isn't Enough: Enumeration Classes for C++](http://www.drdobbs.com/when-enum-just-isnt-enough-enumeration-c/184403955). And, if you want something more encapsulated, try [this approach](http://groups.google.com/group/comp.lang.c++/msg/d9f99ea5f6787c86) from James Kanze. – Don Wakefield Nov 04 '08 at 16:22
  • See also (my question): [What are commonly-used ways to iterate over an enum class in C++?](https://stackoverflow.com/questions/69762598/what-are-commonly-used-ways-to-iterate-over-an-enum-class-in-c) – Gabriel Staples Oct 29 '21 at 02:12

28 Answers28

324

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.

Dávid Tóth
  • 2,788
  • 1
  • 21
  • 46
andreas buykx
  • 12,608
  • 10
  • 62
  • 76
  • 15
    Note that, in the first part of the example, if you want to use 'i' as a Foo enum and not an int, you will need to static cast it like: static_cast(i) – Clayton Mar 17 '09 at 22:30
  • 5
    Also you are skipping Last in the loop. Should be <= Last – Tony Jun 13 '13 at 01:24
  • 28
    @Tony Last is meant to be skipped. If you want to add more enums later, add them before Last... the loop in the first example will still work. By utilizing a "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. – timidpueo Aug 03 '13 at 21:06
  • Except now you've actually allocated memory when an enum, provided it is zero-indexed and strictly continous, can do that task without allocating memory. – Cloud Jan 17 '14 at 23:02
  • It would be awesome to paste @Tony's comment into the answer. I was really confused by that. – tsusanka Oct 24 '14 at 21:30
  • You can also use macros but that means you need to define your enum via macro as well. This way you actually avoid casting and don't have to use vector at all! – ChaoSXDemon Jan 23 '16 at 18:56
  • @tsusanka It operates on the same logic as iterating over an STL containter, actually. Just as `std::end()` returns an "after-the-end" iterator so you can use `i < std::end(whatever)` or `it != std::end(whatever)`, it can be useful to add a dummy value at the end of an `enum` so you can use `i < Last`. Similarly, if an enum is meant to be used for iteration, it can also be useful to add a dummy `First` element, whose underlying value is the same as the actual first element's value. In this answer, for example, it could be something like `First = One`. – Justin Time - Reinstate Monica Mar 31 '16 at 21:18
  • 1
    Note that for this enum definition to be safe for updates one should define a value `UNKNOWN = 0`. Additionally, I would suggest to just drop the `default` case when switching over enum values since it might hide cases where handling of values was forgotten until runtime. Instead one should hardcode all values and use the `UNKNOWN` field to detect incompatibilities. – Benjamin Bannier Apr 13 '17 at 15:08
  • 2
    @timidpueo That's why I prefer to call the last entry `Count`. Makes it a little more obvious. – Cerno Aug 14 '20 at 08:27
  • 1
    @Cerno Right. Also, it's wise to add a comment such as "Do not assign values because this is iterated over. See xxx::count." – Jeff Learman Apr 06 '21 at 17:15
  • 1
    @cloud: The compiler will optimize out the "extra" variable. Removing temporary variables that clarify the code is not a good way to optimize, because it (a) usually doesn't actually optimize, and (b) it reduces clarity. – Jeff Learman Apr 06 '21 at 17:16
82
#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;
}
zdf
  • 4,382
  • 3
  • 18
  • 29
  • Thanks! Note that if you're crossing files/classes and if MS compatibility is giving you issues with header-declared non-integer constants, it helps under my compiler to explicitly put the size in the type in the header: `static const Type All[3];` and then I'm able to initialize in the source: `const MyEnum::Type MyEnum::All[3] = { a, b, c };` Before doing that, I was getting obnoxious `Error in range-based for...` errors (because the array had an unknown size). Figured this out thanks to [a related answer](http://stackoverflow.com/a/7939414/527489) – sage Mar 04 '15 at 05:47
  • 1
    The array version is very friendly of copy paste. The most satisfactory answer besides, "NO" or "only for sequential". Probably macro friendly even. – Paulo Neves Sep 29 '16 at 15:14
  • 2
    this might be a good solution for enums with small number of items, but for enums with big number of items it must not fit well. – kato2 Sep 04 '19 at 15:48
39

With c++11, there actually is an alternative: writing a 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)

425nesp
  • 6,936
  • 9
  • 50
  • 61
  • please note that the "generic code" is tied to "foo" (see the code about the middle), so you can't actually use it with other enum definitions. – lepe Sep 14 '15 at 07:11
  • 1
    @lepe ? You just make a different typedef for a different enum. – Andrew Lazarus Sep 24 '15 at 21:49
  • 3
    @lepe That's like saying that `std::vector` isn't generic because `std::vector` is tied to `foo`. – Kyle Strand Dec 02 '15 at 21:15
  • @AndrewLazarus, @Kyle: So if I have another enum like: `enum color { green = 20, white = 30, red = 40 }` How can I use the above code without changing the `foo operator*() { ...` part? Can someone explain with an example code? (Sorry my C++ skills are not that advanced yet). – lepe Dec 03 '15 at 00:43
  • @lepe Because of the skip, you would have to specialize operator ++ to use val+=10 in lieu of ++val. – Andrew Lazarus Dec 03 '15 at 02:57
  • @AndrewLazarus: sorry, my bad... I set those values to make it different to foo, but its not what I'm concern about. Please change from my previous comment and set enum to be: `enum color { green, black, white, blue, red }` . How do I need to use the code proposed by Francesco so I can iterate either `foo` or `color` without having to modify his code? If possible, I would like to see an example code. – lepe Dec 03 '15 at 05:16
  • 1
    `typedef Iterator colorIterator;` Make sure you understand how the template instantiations work. – Andrew Lazarus Dec 03 '15 at 17:12
  • @lepe Each enum will have its *own* (template-specialized) iterator type, just like you'd need a different `std::vector` type to hold different types of objects. This is accomplished via template specialization, as in the previous comment. The point is that you don't need to redefine the `Iterator` template for each unique enum type, just like you don't need to redefine the `std::vector` template for each object type; you just specialize it, which can be done with a one-line `typedef`. – Kyle Strand Dec 03 '15 at 18:07
  • @lepe To solve the "skips" problem in a somewhat-generic (though limited) way, see my answer below. Also, note that you can only tag one person in a comment (so I didn't get notified when you tried to tag me). – Kyle Strand Dec 03 '15 at 18:09
  • 2
    Oh, I see the issue -- `foo operator*() { ...` should be `C operator*() { ...`. – Kyle Strand Dec 03 '15 at 23:08
  • 1
    @KyleStrand: You got it! that makes totally sense now. Should the code be updated? Thanks everyone for your explanations. – lepe Dec 04 '15 at 00:44
  • I've actually created a somewhat more generic version here: https://github.com/BatmanAoD/PublicPaste/blob/master/GenericCppCode/EnumIterator.cpp – Kyle Strand Dec 04 '15 at 17:31
  • And by "more generic" I mean that it relies on an overloaded global function called `IsEnumValid` (which could easily be moved into a namespace) to determine whether or not particular int-values are valid enum values, which solves the "skipping" problem. One alternative would be to make the validity-checking function one of the template parameters. Another would be to require the existence of a static array for iteration, as in http://stackoverflow.com/a/26910769/1858225 – Kyle Strand Dec 04 '15 at 17:42
  • When this is a sequential ordinal numeric enum, this would work. What about when you have a disjoint set of bit flags? Including combinations thereof. – mwpowellhtx Dec 03 '18 at 23:47
  • definitely +1, but a) why the `val` member data is of the `int` type but not the `val_t` ? and b) would it be useful to override also the `==` operator along with the `!=` one ? – LRDPRDX May 16 '22 at 09:22
27

too much complicated these solution, i do like that :

enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};

const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };

for (NodePosition pos : NodePositionVector) {
...
}
Enzojz
  • 863
  • 2
  • 9
  • 15
  • I don't know why this was downvoted. It's a reasonable solution. – Paul Brannan Dec 19 '14 at 13:27
  • 22
    I expect it was because the entries need to be maintained in two places. – Ant May 29 '15 at 13:51
  • Does C++ permit the `for (NodePosition pos : NodePositionVector)` syntax? As far as I'm aware this is Java syntax, and you'll need iterators in C++ to do something equivalent. – thegreatjedi Dec 17 '15 at 02:17
  • 4
    @thegreatjedi Since C++11 you can, even simpier : for(auto pos : NodePositionVector) {..} – Enzojz Jan 13 '16 at 12:44
  • 1
    @thegreatjedi It would have been quicker to search, or even compile a test program, than to ask that question. But yes, since C++11 it is perfectly valid C++ syntax, which the compiler translates to the equivalent (and far more verbose/less abstracting) code, usually via iterators; see [cppreference](https://en.cppreference.com/w/cpp/language/range-for). And, as Enzojz said, C++11 also added `auto`, so you don't have to declare the type of the elements explicitly, unless you (A) need to use a conversion operator or (B) don't like `auto` for some reason. Most range-`for` users use `auto` AFAICT – underscore_d Sep 15 '18 at 12:42
  • Here's an extension of that approach: `enum class Foo { a, b }; template struct enum_values; template <> struct enum_values { static constexpr std::array values() { return { Foo::a, Foo::b }; } };` Then you can do `for (Foo f : enum_values::values())`, so you don't need to have variable names named after types (`NodePositionVector`). You still need to maintain it, of course. It would be nice if the language provided this functionality. – Ben Nov 16 '18 at 16:09
  • @Enzojz: Just want to emphasize that this code does not work with any C++ older then 11: `range-based 'for' loops only available with '-std=c++11'` – kuga Jan 05 '21 at 08:44
  • The down side is that you have to maintain `NodePosition` and `NodePositionVector` in sync. – Evgen Sep 21 '21 at 05:06
  • Approach is ok, imlementation is flawed. I do not recommend naming arrays as Vectors (it is outright confusing), and re-using NodePositionVector , while potentially technically valid, is outright confusing, which insults Almighty Readability. -1. – No-Bugs Hare Apr 02 '23 at 05:47
  • How about using MACRO to keep those entries in one place? – cyfex Jul 21 '23 at 08:04
20

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))
    {}
Niki
  • 558
  • 4
  • 10
  • but, what's the use of printing the values bit-wise? – Anu Jan 08 '19 at 01:31
  • 1
    To use enums to create bitmasks. e.g. combine several options in single variable, then using the FOR to test for every option. Fixed my post with better example. – Niki Jan 08 '19 at 08:37
  • I still can't get the use of it(& your post still shows the old example)! Using enum as bitmasks are really helpful, but didn't able to connect the dots! could you please elaborate a bit in your example in details, you can put the additional code as well. – Anu Jan 08 '19 at 19:46
  • @anu Sorry did not see your comment. Added Frog class as bitmask example – Niki Dec 31 '19 at 12:50
  • 1
    Wouldn't you need to start at your 0x1 element? Otherwise you're bitshifting a whole lot 0s, and thereby remain at the first element indefinitely – Tare Feb 16 '21 at 08:09
  • You are correct @Tare , fixed the example. – Niki Apr 14 '21 at 09:00
16

If your enum starts with 0 and the increment is always 1.

enum enumType 
{ 
    A = 0,
    B,
    C,
    enumTypeEnd
};

for(int i=0; i<enumTypeEnd; i++)
{
   enumType eCurrent = (enumType) i;            
}

If not I guess the only why is to create something like a

vector<enumType> vEnums;

add the items, and use normal iterators....

João Augusto
  • 2,285
  • 24
  • 28
12

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, ...
    // ...
}
marski
  • 580
  • 5
  • 11
  • This is a nice option I think. Must be part of a newer C++ spec than I was using when I asked the question I'm guessing? – Adam Jul 15 '19 at 21:08
  • Yes. It iterates over an std::initializer_list. [link](https://en.cppreference.com/w/cpp/utility/initializer_list). – marski Jul 22 '19 at 22:25
9

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)

}
Riot
  • 15,723
  • 4
  • 60
  • 67
7

You can't with an enum. Maybe an enum isn't the best fit for your situation.

A common convention is to name the last enum value something like MAX and use that to control a loop using an int.

Corey Trager
  • 22,649
  • 18
  • 83
  • 121
  • 1
    There are several examples here that demonstrate the opposite. I your own statement you are contradicting yourself (second line). – Niki Dec 31 '19 at 12:54
  • @Niki He is right when telling "can't with enum". All the answers demonstrate "tricks" to iterate over another thing, as if iterating over enum. – Mert Mertce Aug 12 '22 at 16:23
6
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.

Eponymous
  • 6,143
  • 4
  • 43
  • 43
  • I like simple range-like for-loop semantics and I think it will evolve even more which is why I like this solution. – rtischer8277 Mar 24 '20 at 14:56
6

Casting the variable to an int& lets you increment while keeping the type readable.

#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;
}
0
1
2
3
nathanfranke
  • 775
  • 1
  • 9
  • 19
4

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.

Mikhail Semenov
  • 953
  • 8
  • 8
3

You can also overload the increment/decrement operators for your enumerated type.

JohnMcG
  • 8,709
  • 6
  • 42
  • 49
  • 1
    You can't overload any operators on C or C++ enumerated types. Unless you were to create a struct/class that emulated an enumeration of values. – Trevor Hickey Sep 01 '15 at 23:34
  • 2
    C++ allows overloading operators on enums. See https://stackoverflow.com/questions/2571456/operators-overloading-for-enums . – Arch D. Robison May 09 '18 at 21:53
  • Overloading the increment/decrement requires making a decision on what to do when there is an overflow – Eponymous May 27 '19 at 18:39
3

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))
{
    // ...
}
Ethan Bradford
  • 710
  • 8
  • 10
  • 1
    Incrementing can be shortened to `foo = Bar(foo + 1)`. – HolyBlackCat Nov 08 '18 at 19:07
  • Thanks, HolyBlackCat, I've incorporated your excellent suggestion! I also notice that Riot has pretty much this same solution, but conformant with strong typing (and thus more verbose). – Ethan Bradford Nov 08 '18 at 19:49
3

Here are some very readable and easy-to-understand approaches, for both weakly-typed C and C++ regular enums, and strongly-typed C++ enum classes.

I recommend compiling all examples below with -Wall -Wextra -Werror. This gives you the added safety that if you forget to cover any enum value in the switch case your compiler will throw a compile-time error! This forces you to keep your enum definition and switch cases in-sync, which is an extra safety measure for your code. This tip works so long as you:

  1. Cover all enum values in your switch case, and
  2. Do NOT have a default switch case.
  3. Build with the -Wall -Wextra -Werror flags.

I recommend you follow all 3 of those points, as it is a good practice and creates better code.

1. For a standard, weakly-typed C or C++ enum:

C definition (this is also valid C++):

typedef enum my_error_type_e 
{
    MY_ERROR_TYPE_SOMETHING_1 = 0,
    MY_ERROR_TYPE_SOMETHING_2,
    MY_ERROR_TYPE_SOMETHING_3,
    MY_ERROR_TYPE_SOMETHING_4,
    MY_ERROR_TYPE_SOMETHING_5,
    /// Not a valid value; this is the number of members in this enum
    MY_ERROR_TYPE_count,
    // helpers for iterating over the enum
    MY_ERROR_TYPE_begin = 0,
    MY_ERROR_TYPE_end = MY_ERROR_TYPE_count,
} my_error_type_t;

C++ definition:

enum my_error_type_t 
{
    MY_ERROR_TYPE_SOMETHING_1 = 0,
    MY_ERROR_TYPE_SOMETHING_2,
    MY_ERROR_TYPE_SOMETHING_3,
    MY_ERROR_TYPE_SOMETHING_4,
    MY_ERROR_TYPE_SOMETHING_5,
    /// Not a valid value; this is the number of members in this enum
    MY_ERROR_TYPE_count,
    // helpers for iterating over the enum
    MY_ERROR_TYPE_begin = 0,
    MY_ERROR_TYPE_end = MY_ERROR_TYPE_count,
};

C or C++ iteration over this weakly-typed enum:

Note: incrementing an enum by doing my_error_type++ is not allowed--not even on C-style enums, so we must do this instead: my_error_type = (my_error_type_t)(my_error_type + 1). Notice that my_error_type + 1 is allowed, however, since this weak enum is automatically implicitly cast to an int here to make this addition possible withOUT having to manually cast it to an int like this: my_error_type = (my_error_type_t)((int)my_error_type + 1).

for (my_error_type_t my_error_type = MY_ERROR_TYPE_begin; 
        my_error_type < MY_ERROR_TYPE_end;
        my_error_type = (my_error_type_t)(my_error_type + 1)) 
{
    switch (my_error_type) 
    {
        case MY_ERROR_TYPE_SOMETHING_1:
            break;
        case MY_ERROR_TYPE_SOMETHING_2:
            break;
        case MY_ERROR_TYPE_SOMETHING_3:
            break;
        case MY_ERROR_TYPE_SOMETHING_4:
            break;
        case MY_ERROR_TYPE_SOMETHING_5:
            break;
        case MY_ERROR_TYPE_count:
            // This case will never be reached.
            break;
    }
}

2. For a scoped, strongly-typed C++ enum class:

C++ definition:

enum class my_error_type_t
{
    SOMETHING_1 = 0,
    SOMETHING_2,
    SOMETHING_3,
    SOMETHING_4,
    SOMETHING_5,
    /// Not a valid value; this is the number of members in this enum
    count,
    // helpers for iterating over the enum
    begin = 0,
    end = count,
};

C++ iteration over this strongly-typed enum:

Notice the extra (size_t) cast (or (int) would be acceptable too) required to forcefully increment the enum class variable! I also chose to use the C++-style static_cast<my_error_type_t> cast here, but a C-style (my_error_type_t) cast, as done above, would have been fine as well.

for (my_error_type_t my_error_type = my_error_type_t::begin; 
        my_error_type < my_error_type_t::end;
        my_error_type = static_cast<my_error_type_t>((size_t)my_error_type + 1)) 
{
    switch (my_error_type) 
    {
        case my_error_type_t::SOMETHING_1:
            break;
        case my_error_type_t::SOMETHING_2:
            break;
        case my_error_type_t::SOMETHING_3:
            break;
        case my_error_type_t::SOMETHING_4:
            break;
        case my_error_type_t::SOMETHING_5:
            break;
        case my_error_type_t::count:
            // This case will never be reached.
            break;
    }
}

Also notice the scoping. In the C++ strongly-typed enum class I used my_error_type_t:: to access each scoped enum class member. But, in the C-style weakly-typed regular enum, very similar scoping can be achieved, as I demonstrated, simply be prefixing each enum member name with MY_ERROR_TYPE_. So, the fact that the C++ strongly-typed enum class adds scoping doesn't really add much value--it's really just a personal preference in that regard. And the fact that the C++ strongly-typed enum class has extra type-safety also has pros and cons. It may help you in some cases but it definitely makes incrementing the enum and iterating over it a pain-in-the-butt, which, honestly, means it is doing its job. By making it harder to increment the scoped enum class variable as though it was an integer, the C++ strongly-typed enum class is doing exactly what it was designed to do. Whether or not you want that behavior is up to you. Personally, I frequently do not want that behavior, and so it is not uncommon for me to prefer to use C-style enums even in C++.

See also:

  1. [my answer] Is there a way to initialize a vector by index in c++11?
  2. [my Q&A] What are commonly-used ways to iterate over an enum class in C++?
  3. My answer on some of the differences between enum classes (strongly-typed enums) and regular enums (weakly-typed enums) in C++: How to automatically convert strongly typed enum into int?
  4. Some of my personal notes on the -Wall -Wextra -Werror and other build options, from my eRCaGuy_hello_world repo.
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
2

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);
}
Niels Holst
  • 586
  • 4
  • 9
2

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

Aryaman Gupta
  • 616
  • 1
  • 8
  • 20
1

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.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
  • This was written ~5 years after `decltype` became standard C++, so you should not recommend the outdated `typeof` from ancient GCC. Vaguely recent GCC handles `decltype` just fine. There are other issues: C-style casts are discouraged, & macros worse. Proper C++ features can give the same generic functionality. This would be better rewritten to use `static_cast` & a template function: `template auto inc_enum(T const t) { return static_cast(static cast(t) + 1); }`. And casts aren't needed for non-`enum class`. Alternatively, operators can be overloaded per `enum` type (TIL) – underscore_d Sep 15 '18 at 12:55
1

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.

LAL
  • 480
  • 5
  • 13
  • A downvote was cast on this post. Any reason why would it will not answer to the question ? – LAL Dec 13 '19 at 21:07
  • The reason is probably because this is a terrible solution architecturally speaking: it forces you to write global-meant-to logic binded to a specific component (your enumeration), moreover if your enumeration does change for whatever reason you are forced to edit your ++ operator too, as an approach it is not sustainable for any medium-large scale project, it is not a surprise it comes from a Bjarne Stroustrup's recommendation, back in the days software architecture was like science fiction – Manjia Mar 05 '20 at 11:37
  • 1
    Original question is about having operator to an `enum`. It wasn't a architectural question. I don't believe that in 2013 C++ was a science fiction. – LAL Mar 06 '20 at 14:03
  • I don't think people here are looking for bad solutions, which this one definitely is, and therefore downvoted. I just added my downvote too btw – Manjia Mar 03 '21 at 11:11
  • I upvote as it is an interesting concept, functional, and the other statements are personal bias. – Andrew Truckle Mar 17 '22 at 07:26
1

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.

Scott M
  • 684
  • 7
  • 14
  • I don't believe this should be downvoted. It's a portable solution that works with enums that are not consecutive; and other answers involving arrays were upvoted. Mine has the advantage that you don';t have to define the enum values twice and keep two definitions in sync, and it showcases a useful trick for interpreting tokens multiple ways with undef and define that is generally applicable to many problems. Unless and until we get enum ++, -- and iterators, there's simply no clean way to do it. This is the cleanest of the workarounds. – Scott M Sep 21 '21 at 18:50
1

(Taking Marski's answer as a big hint...)

Since the body of an enum definition is the same as an initialiser list it is possible to do this without repeating the item list if we use a simple macro to write out the values:

#define ITEM_LIST_MACRO Wolf, Goat, Cabbage

enum Item { ITEM_LIST_MACRO }; // Define the enum

// Now iterate through it
for (auto item : { ITEM_LIST_MACRO }) {
}

Pros: Simple, no repetition, and no need to maintain annoying first/last sentinel values. (Indeed I think this might be the only solution suggested so far that does not require the user to remember to update an 'end' marker when a new item is added to the list.)

Cons: Doesn't work with scoped enums (enum class) because the initialiser list would need the scope (Item::Wolf etc). Also doesn't work if you want to specify the values of the enum members rather than having them defaulted.

void
  • 21
  • 3
0

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.

kcrossen
  • 159
  • 2
  • 4
0
typedef enum{
    first = 2,
    second = 6,
    third = 17
}MyEnum;

static const int enumItems[] = {
    first,
    second,
    third
}

static const int EnumLength = sizeof(enumItems) / sizeof(int);

for(int i = 0; i < EnumLength; i++){
    //Do something with enumItems[i]
}
0

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:

  1. You should be able to add a 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 };.
  2. I bet there's a way to use the compiler's switch-covers-all-enum-values to write allValuesArray such that it errors if the enum has added a value.
Ben
  • 9,184
  • 1
  • 43
  • 56
  • That's interesting. I ended up using only `inline constexpr auto allValuesArray() { return std::array{ MyEnum::foo, MyEnum::bar, MyEnum::baz }; }` since I need to spell it out one by one anyway. That's for me the simplest solution. (btw: with your code I saw clang-7 crashing. fun fun fun XD) – kwach Dec 08 '20 at 02:23
0

Using a lambda, I found this the best (modern) way of looping over enums. This highly improves the abstraction. Can even make it a template, so it's applicable to any enum. This code neither gives you issues with 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
});
jaques-sam
  • 2,578
  • 1
  • 26
  • 24
-1

Most solution are based on loops over the (MIN, MAX) range but overlook the fact that might be holes in the enum.

My suggestions is:

        for (int i = MYTYPE_MIN; i <= MYTYPE_MAX; i++) {
            if (MYTYPE_IsValid(i)) {
                MYTYPE value = (MYTYPE)i;
                // DoStuff(value)
            }   
        }   
        
SylvainD
  • 1,743
  • 1
  • 11
  • 27
  • Awesome! So now all we need to do is implement `MYTYPE_IsValid`. Doing so leaves you with two options: `1` An implementation whose name [doesn't lie](https://stackoverflow.com/a/4969304/1889329) but is useless in always returning `true`. `2` An implementation that does something else than its name implies, but cannot be implemented in a generic fashion. It becomes invalid with every change to the `enum` definition, that cannot be diagnosed. – IInspectable Oct 13 '21 at 07:34
  • @IInspectable YMMV but I think it is not that hard to define a maintainable MYTYPE_IsValid(int) function by relying on a switch case and warnings related to non-handled enumerated value in switch case. This type of function is also useful to perform checks before casting the value when you get your value as a raw integer. (For what it's worth, my snippet was initially written for protobuf enums which do define an IsValid function). – SylvainD Oct 20 '21 at 11:35
-2

C++ doesn't have introspection, so you can't determine this kind of thing at run-time.

kͩeͣmͮpͥ ͩ
  • 7,783
  • 26
  • 40
  • 2
    Could you explain to me why "introspection" would be needed to iterate over an enum? – Jonathan Mee Sep 07 '16 at 18:50
  • 1
    Maybe the term is *Reflection*? – kͩeͣmͮpͥ ͩ Sep 08 '16 at 11:15
  • 2
    I'm trying to say 2 things: 1) Per many other answers C++ can accomplish this so if you're going to say it cannot, a link or further clarification is required. 2) In it's current form this is at best a comment, certainly not an answer. – Jonathan Mee Sep 08 '16 at 11:33
  • Downvote my answer then - I think you've more than justified it – kͩeͣmͮpͥ ͩ Sep 08 '16 at 15:49
  • 2
    I'll again cram in 2 comments: 1) I don't downvote because I find that receiving a downvote demotivates site participation, I find that counterproductive 2) I still don't understand what you're trying to say but it sounds like you understand something I don't in which case I'd prefer you elaborate rather than delete a downvoted answer. – Jonathan Mee Sep 08 '16 at 16:04
  • C++ indeed supports type introspection. See typeid and dynamic_cast – user3063349 Apr 27 '17 at 08:36
  • Introspection is the correct term (no manipulation, only examination). While the answers statement is wrong due to RTTI methods via `typeid` and `dynamic_cast`, both are not a solution for the problem. So technically, "the introspection of C++ does not cover looking up enum values" or something would be a better answer. – Roi Danton Jun 03 '18 at 17:54
-2

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.

mathreadler
  • 447
  • 5
  • 16