Loop over enum values

F

Fred Zwarts

What is the recommended way to loop over all enum values of a certain enum type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;

then

for (E x = A; x <= D; ++x) { ... }

does not work because

1) Some compilers complain that the ++ operator is not defined for enum types.
2) Other compilers complain that the test x<=D is always true.
3) Other compiler compile, but at run time illegal values are assigned to x.

I can, of course, define a ++ operator for E, but the code would probably consist
of a switch ... case construction, which is error prone, because modification of
the definition of E does not automatically adjust the cases within the ++ operator.
The problem that x<=D is always true could be solved by using a conditional break
at the end of the loop.
if (x==D) break;
Has someone found a simpler solution?

Fred.Zwarts.
 
M

mlimber

Fred said:
What is the recommended way to loop over all enum values of a certain enum type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;

then

for (E x = A; x <= D; ++x) { ... }

does not work because

1) Some compilers complain that the ++ operator is not defined for enum types.
2) Other compilers complain that the test x<=D is always true.
3) Other compiler compile, but at run time illegal values are assigned to x.

I can, of course, define a ++ operator for E, but the code would probably consist
of a switch ... case construction, which is error prone, because modification of
the definition of E does not automatically adjust the cases within the ++ operator.
The problem that x<=D is always true could be solved by using a conditional break
at the end of the loop.
if (x==D) break;
Has someone found a simpler solution?

Fred.Zwarts.

I generally define an enum with min and max values and then run for
loops using those:

enum E { MIN, A=MIN, B, C, D, MAX=D };
for( E e=MIN; e <= MAX; e = E( e+1 ) ) {...}

That way, if the enum changes by adding or subtracting values, my for
loops don't change because I have already updated MIN and MAX, which
practice is admittedly somewhat fragile but it is less so than not
using MIN and MAX, IMHO.

Cheers! --M
 
V

Victor Bazarov

Fred said:
What is the recommended way to loop over all enum values of a certain enum type?

You can overload ++ for the enum, but you will have to manually ensure
that the next value is the one from the declared/defined enumerators.
Consider the following definition:

typdef enum {A=2, B, C=5, D} E;

then

for (E x = A; x <= D; ++x) { ... }

does not work because

1) Some compilers complain that the ++ operator is not defined for enum types.

And that's true.
2) Other compilers complain that the test x<=D is always true.

That's not necessarily true.
3) Other compiler compile, but at run time illegal values are assigned to x.

No such thing as "illegal" as long as the value is within the range
represented by the enum base type.
I can, of course, define a ++ operator for E, but the code would probably consist
of a switch ... case construction, which is error prone, because modification of
the definition of E does not automatically adjust the cases within the ++ operator.

That's what you'll have to do if you want to iterate "over" those values.
Enumerations are not there to be iterated over. They represent "typed
constants". If you want to iterate, use an array or a standard container.
The problem that x<=D is always true could be solved by using a conditional break
at the end of the loop.
if (x==D) break;
Has someone found a simpler solution?

No such thing.

V
 
G

Gavin Deane

mlimber said:
I generally define an enum with min and max values and then run for
loops using those:

enum E { MIN, A=MIN, B, C, D, MAX=D };
for( E e=MIN; e <= MAX; e = E( e+1 ) ) {...}

That way, if the enum changes by adding or subtracting values, my for
loops don't change because I have already updated MIN and MAX, which
practice is admittedly somewhat fragile but it is less so than not
using MIN and MAX, IMHO.

I don't thnik that helps the OP's "at run time illegal values are
assigned to e" problem. In the OP's code, not every integer between MIN
and MAX had a corresponding value in the enum.

Gavin Deane
 
R

roberts.noah

mlimber said:
I generally define an enum with min and max values and then run for
loops using those:

enum E { MIN, A=MIN, B, C, D, MAX=D };
for( E e=MIN; e <= MAX; e = E( e+1 ) ) {...}

That way, if the enum changes by adding or subtracting values, my for
loops don't change because I have already updated MIN and MAX, which
practice is admittedly somewhat fragile but it is less so than not
using MIN and MAX, IMHO.

The OP has bigger problems than that caused by assigning values to the
enums. There are ranges within the overall range that are invalid.

I do the same thing but I don't assign MAX to the last value. That way
I don't have to use <= but can just use <. I'm of the school of
thought that if you are using <= in a C or C++ loop then you should be
double checking that there is no logic error because it isn't natural
for most situations.
 
V

Victor Bazarov

mlimber said:
Fred said:
What is the recommended way to loop over all enum values of a certain enum type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;
[..]

I generally define an enum with min and max values and then run for
loops using those:

enum E { MIN, A=MIN, B, C, D, MAX=D };
for( E e=MIN; e <= MAX; e = E( e+1 ) ) {...}

That way, if the enum changes by adding or subtracting values, my for
loops don't change because I have already updated MIN and MAX, which
practice is admittedly somewhat fragile but it is less so than not
using MIN and MAX, IMHO.

Notice the difference between the two definitions: Yours doesn't have
gaps as the OP's. Essentially what you have here is not a set of
unrelated (in values) typed constants but a range. It is generally
allowed to have any order of values in there. Since those values have
no particular ordering runing over then with a regular ++ makes no sense.

enum NoParticularOrder { ONE = 777, TWO = 22, THREE = 3 };

Now, try getting the sequence [ ONE, TWO, THREE ] out of it. There is no
way except to provide a custom ++ operator in which there is a 'switch'
statement that implements the business logic of "moving to the next value"
"along" that enumeration.

V
 
K

Kai-Uwe Bux

Fred said:
What is the recommended way to loop over all enum values of a certain enum
type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;

then

for (E x = A; x <= D; ++x) { ... }

does not work because

1) Some compilers complain that the ++ operator is not defined for enum
types. 2) Other compilers complain that the test x<=D is always true.
3) Other compiler compile, but at run time illegal values are assigned to
x.

Your phrase "illegal values" probably refers to values not defined by any of
the enumerators. Be informed that those values are actually legal:

[Standard, clause 7.2/6]

For an enumeration where emin is the smallest enumerator and emax is the
largest, the values of the enumeratio are the values of the underlying
type in the range bmin to bmax, where bmin and bmax are, respectively, the
smallest and largest values of the smallest bit-field that can store emin
and emax.81) It is possible t define an enumeration that has values not
defined by any of its enumerators.

I can, of course, define a ++ operator for E, but the code would probably
consist of a switch ... case construction, which is error prone, because
modification of the definition of E does not automatically adjust the
cases within the ++ operator. The problem that x<=D is always true could
be solved by using a conditional break at the end of the loop.
if (x==D) break;
Has someone found a simpler solution?

Since the non-enumerated values actually are legal, you have to decide
whether you want to include them in the iteration or not. If you do, you
can use casting and arithmetic of the underlying integral type. If not,
your could (a) make sure that there are no gaps or (b) use the switch
statement.


Best

Kai-Uwe Bux
 
R

roberts.noah

Victor said:
Notice the difference between the two definitions: Yours doesn't have
gaps as the OP's. Essentially what you have here is not a set of
unrelated (in values) typed constants but a range. It is generally
allowed to have any order of values in there. Since those values have
no particular ordering runing over then with a regular ++ makes no sense.

enum NoParticularOrder { ONE = 777, TWO = 22, THREE = 3 };

Now, try getting the sequence [ ONE, TWO, THREE ] out of it. There is no
way except to provide a custom ++ operator in which there is a 'switch'
statement that implements the business logic of "moving to the next value"
"along" that enumeration.

A lookup table would probably be more manageable. The OP probably also
wants a class built just to deal with this thing; then they could make
some sort of iterator to abstract the mess of looping through the
values.
 
M

mlimber

Victor said:
mlimber said:
Fred said:
What is the recommended way to loop over all enum values of a certain enum type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;
[..]

I generally define an enum with min and max values and then run for
loops using those:

enum E { MIN, A=MIN, B, C, D, MAX=D };
for( E e=MIN; e <= MAX; e = E( e+1 ) ) {...}

That way, if the enum changes by adding or subtracting values, my for
loops don't change because I have already updated MIN and MAX, which
practice is admittedly somewhat fragile but it is less so than not
using MIN and MAX, IMHO.

Notice the difference between the two definitions: Yours doesn't have
gaps as the OP's. Essentially what you have here is not a set of
unrelated (in values) typed constants but a range. It is generally
allowed to have any order of values in there. Since those values have
no particular ordering runing over then with a regular ++ makes no sense.

enum NoParticularOrder { ONE = 777, TWO = 22, THREE = 3 };

Now, try getting the sequence [ ONE, TWO, THREE ] out of it. There is no
way except to provide a custom ++ operator in which there is a 'switch'
statement that implements the business logic of "moving to the next value"
"along" that enumeration.

V

As Victor and others point out, I missed the gap, and a switch (or a
masked version of it which don't seem to hold much advantage over a
switch) is required.

Cheers! --M
 
S

shaun

"Fred Zwarts said:
What is the recommended way to loop over all enum values of a certain enum
type?

Consider the following definition:

typdef enum {A=2, B, C=5, D} E;
.....
if (x==D) break;
Has someone found a simpler solution?

Fred.Zwarts.

I'm going to second-guess your intention and suggest an alternative:
I guess you have some 'magic numbers' which you are coding in an enum.
Why not make a const vector, and initialize from an old fashioned array:

e.g somewhere in your cpp file:

const int intTable[]={ 2, 3, 5, 6 };

template <class T>
T* endof( T * const parray){
int numElements = sizeof(parray)/sizeof(parray[0]);
return parray + numElements;
}

const vector<int> E(intTable, endof(intTable));//range constructor



The 'endof' function can deal with different types of table. The
intTable can be added to without changing the remainder of the code. The
vector, of course, can be iterated over.

Good luck

shaun
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,233
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top