42

In C++, Is it possible to enumerate over an enum (either runtime or compile time (preferred)) and call functions/generate code for each iteration?

Sample use case:

enum abc
{    
    start
    a,
    b,
    c,
    end
}    
for each (__enum__member__ in abc)
{    
    function_call(__enum__member__);    
}

Plausible duplicates:

2
  • How do you suppose to pick function for call? Could you post some pseudo code how do you suppose to do it? It could help us to help you. Commented Sep 7, 2009 at 20:12
  • For runtime look at stackoverflow.com/questions/1292426/…. (If it weren't for compile-time, your question would be an exact duplicate of it.) Commented Sep 7, 2009 at 20:57

9 Answers 9

60

To add to StackedCrooked's answer, you can overload operator++, operator-- and operator* and have iterator-like functionality.

enum Color {
    Color_Begin,
    Color_Red = Color_Begin,
    Color_Orange,
    Color_Yellow,
    Color_Green,
    Color_Blue,
    Color_Indigo,
    Color_Violet,
    Color_End
};

namespace std {
template<>
struct iterator_traits<Color>  {
  typedef Color  value_type;
  typedef int    difference_type;
  typedef Color *pointer;
  typedef Color &reference;
  typedef std::bidirectional_iterator_tag
    iterator_category;
};
}

Color &operator++(Color &c) {
  assert(c != Color_End);
  c = static_cast<Color>(c + 1);
  return c;
}

Color operator++(Color &c, int) {
  assert(c != Color_End);
  ++c;
  return static_cast<Color>(c - 1);
}

Color &operator--(Color &c) {
  assert(c != Color_Begin);
  return c = static_cast<Color>(c - 1);
}

Color operator--(Color &c, int) {
  assert(c != Color_Begin);
  --c;
  return static_cast<Color>(c + 1);
}

Color operator*(Color c) {
  assert(c != Color_End);
  return c;
}

Let's test with some <algorithm> template:

void print(Color c) {
  std::cout << c << std::endl;
}

int main() {
  std::for_each(Color_Begin, Color_End, &print);
}

Now, Color is a constant bidirectional iterator. Here is a reusable class I coded while doing it manually above. I noticed it could work for many more enums, so repeating the same code all over again is quite tedious.

// Code for testing enum_iterator
// --------------------------------

namespace color_test {
enum Color {
  Color_Begin,
  Color_Red = Color_Begin,
  Color_Orange,
  Color_Yellow,
  Color_Green,
  Color_Blue,
  Color_Indigo,
  Color_Violet,
  Color_End
};

Color begin(enum_identity<Color>) {
  return Color_Begin;
}

Color end(enum_identity<Color>) {
  return Color_End;
}
}

void print(color_test::Color c) {
  std::cout << c << std::endl;
}

int main() {
  enum_iterator<color_test::Color> b = color_test::Color_Begin, e;
  while(b != e)
    print(*b++);
}

An implementation follows.

template<typename T>
struct enum_identity {
  typedef T type;
};

namespace details {
void begin();
void end();
}

template<typename Enum>
struct enum_iterator
  : std::iterator<std::bidirectional_iterator_tag,
                  Enum> {
  enum_iterator():c(end()) { }

  enum_iterator(Enum c):c(c) {
    assert(c >= begin() && c <= end());
  }

  enum_iterator &operator=(Enum c) {
    assert(c >= begin() && c <= end());
    this->c = c;
    return *this;
  }

  static Enum begin() {
    using details::begin; // re-enable ADL
    return begin(enum_identity<Enum>());
  }

  static Enum end() {
    using details::end; // re-enable ADL
    return end(enum_identity<Enum>());
  }

  enum_iterator &operator++() {
    assert(c != end() && "incrementing past end?");
    c = static_cast<Enum>(c + 1);
    return *this;
  }

  enum_iterator operator++(int) {
    assert(c != end() && "incrementing past end?");
    enum_iterator cpy(*this);
    ++*this;
    return cpy;
  }

  enum_iterator &operator--() {
    assert(c != begin() && "decrementing beyond begin?");
    c = static_cast<Enum>(c - 1);
    return *this;
  }

  enum_iterator operator--(int) {
    assert(c != begin() && "decrementing beyond begin?");
    enum_iterator cpy(*this);
    --*this;
    return cpy;
  }

  Enum operator*() {
    assert(c != end() && "cannot dereference end iterator");
    return c;
  }

  Enum get_enum() const {
    return c;
  }

private:
  Enum c;
};

template<typename Enum>
bool operator==(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
  return e1.get_enum() == e2.get_enum();
}

template<typename Enum>
bool operator!=(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
  return !(e1 == e2);
}
Sign up to request clarification or add additional context in comments.

Comments

42

C++ currently does not provide enumerator iteration. Despite that, the need sometimes arises for this. A common workaround is to add values that mark the beginning and the ending. For example:

enum Color
{
    Color_Begin,
    Color_Red = Color_Begin,
    Color_Orange,
    Color_Yellow,
    Color_Green,
    Color_Blue,
    Color_Indigo,
    Color_Violet,
    Color_End
};

void foo(Color c)
{
}


void iterateColors()
{
    for (size_t colorIdx = Color_Begin; colorIdx != Color_End; ++colorIdx)
    {
        foo(static_cast<Color>(colorIdx));
    }
}

Comments

3

Neither is possible without a little manual labour. A lot of the work can be done by macros, if you’re willing to delve into that area.

Comments

2

Expanding on what Konrad says, one possible idiom in the case of "generate code for each iteration" is to use an included file to represent the enumeration:

File mystuff.h

#ifndef LAST_ENUM_ELEMENT
#define LAST_ENUM_ELEMENT(ARG) ENUM_ELEMENT(ARG)
#endif

ENUM_ELEMENT(foo)
ENUM_ELEMENT(bar)
LAST_ENUM_ELEMENT(baz)

// Not essential, but most likely every "caller" should do it anyway...
#undef LAST_ENUM_ELEMENT
#undef ENUM_ELEMENT

enum.h:

// The include guard goes here (but mystuff.h doesn't have one)

enum element {
    #define ENUM_ELEMENT(ARG) ARG,
    #define LAST_ENUM_ELEMENT(ARG) ARG
    #include "mystuff.h"
}

File main.cpp

#include "enum.h"
#define ENUM_ELEMENT(ARG) void do_##ARG();
#include "mystuff.h"

element value = getValue();
switch(value) {
    #define ENUM_ELEMENT(ARG) case ARG: do_##ARG(); break;
    #include "mystuff.h"
    default: std::terminate();
}

So, to add a new element "qux", you add it to file mystuff.h and write the do_qux function. You don't have to touch the dispatch code.

Of course if the values in your enum need to be specific non-consecutive integers, then you end up maintaining the enum definition and the ENUM_ELEMENT(foo)... list separately, which is messy.

Comments

1

No

However, you could define your own class that implements enum-like features with iterations. You may recall a trick from the pre 1.5 Java days, called the "type safe enum design pattern". You could do the C++ equivalent.

Comments

1

I usually do that like this:

enum abc
{    
    abc_begin,
    a = abc_begin,
    b,
    c,
    abc_end
};

void foo()
{
    for( auto&& r : range(abc_begin,abc_end) )
    {
        cout << r;
    }
}


range is completely generic, and defined like follows:

template <typename T>
class Range
{
public:
    Range( const T& beg, const T& end ) : b(beg), e(end) {}
    struct iterator
    {
        T val;
        T operator*() { return val; }
        iterator& operator++() { val = (T)( 1+val ); return *this; }
        bool operator!=(const iterator& i2) { return val != i2.val; }
    };
    iterator begin() const { return{b}; }
    iterator end() const { return{e}; }
private:
    const T& b;
    const T& e;
};

template <typename T>
Range<T> range( const T& beg, const T& end ) { return Range<T>(beg,end); }

Comments

1

This seems hacky to me, but it may suit your purposes:

enum Blah {
  FOO,
  BAR,
  NUM_BLAHS
};

// Later on
for (int i = 0; i < NUM_BLAHS; ++i) {
  switch (i) {
  case FOO:
    // Foo stuff
    break;
  case BAR:
    // Bar stuff
    break;
  default:
    // You're missing a 'case' statement
  }
}

If you need a special start value, you can make that a constant and set it in your enum. I didn't check if this compiles, but it should be close to being there :-).

I think this approach might be a good balance for your use case. Use it if you don't need to do this for a bunch of different enumerated types and you don't want to deal with preprocessor stuff. Just make sure you comment and probably add a TODO to change it at a later date to something better :-).

4 Comments

The for and nested switch are utterly useless/meaningless since you use each of the consecutive values anyway. Just omit both and execute foo stuff, followed by bar stuff etc. directly.
This is only useful in a test program where you run a series of tests. The start/end conditions would be variables so if you want to only run one test you set start = end: for (int i = start; i <= end; ++i) { .... } In all other cases, I agree with Konrad: switch inside a for is probably a bad design.
A for loop to hit each case of a switch statement? Please. This is Stackoverflow, not thedailywtf.com. That's just a needlessly complicated way to do "foo stuff", then "bar stuff". That doesn't require any sort of flow control.
@Konrad and Alan: I think the point of this would be to make sure you hit every enum. If you crash or output a warning or something in the default statement, you at least recognize at runtime that you forgot to include a new case after adding a new enum. I really wasn't sure what the application was of the OP, so I just put down what I thought was the simplest way to do what was asked. It seems the original question was updated and this doesn't make sense anymore and I misunderstood the original question. However...this is slightly better than just calling each method separately.
0

You can perform some of the proposed runtime techniques statically with TMP.

#include <iostream>

enum abc
{
    a,
    b,
    c,
    end
};

void function_call(abc val)
{
    std::cout << val << std::endl;
}

template<abc val>
struct iterator_t
{
    static void run()
    {
        function_call(val);

        iterator_t<static_cast<abc>(val + 1)>::run();
    }
};

template<>
struct iterator_t<end>
{
    static void run()
    {
    }
};

int main()
{
    iterator_t<a>::run();

    return 0;
}

The output from this program is:

0
1
2

See Chapter 1 of Abrahams, Gurtovoy "C++ Template Metaprogramming" for a good treatment of this technique. The advantage to doing it this way over the proposed runtime techniques is that, when you optimize this code, it can inline the statics and is roughly equivalent to:

function_call(a);
function_call(b);
function_call(c);

Inline function_call for even more help from the compiler.

The same criticisms of other enumeration iteration techniques apply here. This technique only works if your enumeration increments continuously from a through end by ones.

Comments

0

I love templating, but I'm going to make note of this for my future/other peoples' usage, so we're not lost with any of the above.

Enums are convenient for the sake of comparing things in a known ordered fashion. They are typically used hard coded into functions for the sake of readability against integer values. Somewhat similar to preprocessor definitions, with the exception that they are not replaced with literals, but they are kept and accessed at runtime.

If we had an enum defining HTML error codes and we knew that error codes in the 500s are server errors, it might be nicer to read something like:

enum HtmlCodes {CONTINUE_CODE=100,
                CLIENT_ERROR=400,
                SERVER_ERROR=500,
                NON_STANDARD=600};

if(errorCode >= SERVER_ERROR && errorCode < NON_STANDARD)

than

if(errorCode >= 500 && errorCode < 600)

The key part is this, they are similar to arrays! But they are used to cast integer values.

Short example:

enum Suit {Diamonds, Hearts, Clubs, Spades};

// Do something with values in the enum past "Hearts" in this case
for(int i=0; i<4; i++) {
   // It could also use i or Hearts, because the enum
   // will turn these both back into an int
   if((Suit)(i) > 1)
   {
      // Whatever we'd like to do with (Suit)(i)
   }
}

Oftentimes, enums are also used with char* arrays or string arrays so that you could print some message with the associated value. Normally they're just arrays with the same set of values in the enum, like so:

char* Suits[4] = {"Diamonds", "Hearts", "Clubs", "Spades"};
// It is getting a little redundant
cout << Suits[Clubs] << endl;

// We might want to add this to the above
//cout << Suits[(Suit)(i)] << endl;

And of course it's even nicer to create a generic class which handles iteration for enums like the answers above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.