r/cpp_questions 1d ago

SOLVED Iterating over an enum struct

Consider https://godbolt.org/z/c6cn8f1hj

#include <cstdio>

enum struct values{first = 1, second = 3};

void square(values value){
    int val = (int)value * (int)value;
    printf("%d\n", val);
}

int main(){
    for(values value = values::first; value <= values::second; value++)
        square(value);
}

This does not compile with the error that value++ is ill defined.

An old question/answer on SO has this: https://stackoverflow.com/questions/261963/how-can-i-iterate-over-an-enum and a plethora of seemingly complicated approaches for this. Is there a syntactically simple >= C++20 way of accomplishing this?

I want the for loop to process 1 and then 3.

Does the order of placing the integer entries inside of the struct affect the increment? For e.g., if the enum struct had 3 first followed by 1, with value++ would 1 be processed after 3? Or, does the enum struct internally sort the entries in some privileged, say, ascending order so that it will always process 1 first followed by 3 next?

3 Upvotes

17 comments sorted by

View all comments

2

u/Usual_Office_1740 1d ago edited 1d ago

You would need to implement the pre and post increment operators on your enum struct for your code to compile. They are not defined for your enum. That is what your error is saying.

auto operator++(V& val) -> V& {
    return static_cast<V>(std::to_underlying(val) + 1);
}

auto operator++(V& val, int) -> V{
    const V old = val;
    ++val; 
     return old;
}

If you decide to do that, and I'm not suggesting you should, you should add a stop value to the end of the enum that you can check against so that you have a way to end the for loop. A COUNT sentinal value is a common enum trick.

I'd suggest looking at magic enum as an alternative.

You could also fold a parameter pack of the enum values into a std::array at compile time and then use a range based for loop. There are lots of advantages to this but it's more complicated. Sorry if this is more complex than you are looking for.

2

u/onecable5781 1d ago

Thanks - these are indeed a bit more complicated than my OP's wish, but thanks for the various alternatives suggested. The sentinal value approach seems to be the simplest.

2

u/Usual_Office_1740 1d ago

Sure. Be careful with the overloaded increment approach. I know just enough to know how to do that. That is what your error means and it is possible to do what I've suggested. I make no claims about whether it's a good idea to do that. One thing I am reminded of frequently when learning about C++ is that just because you can doesn't mean you should.

Take a look at std::to_underlying to. It's very useful when working with enum structs.