469,623 Members | 1,409 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,623 developers. It's quick & easy.

Loop over enum values

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.
Jan 25 '06 #1
9 48177
Fred Zwarts wrote:
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

Jan 25 '06 #2
Fred Zwarts wrote:
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
Jan 25 '06 #3

mlimber wrote:
Fred Zwarts wrote:
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.


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

Jan 25 '06 #4

mlimber wrote:
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.

Jan 25 '06 #5
mlimber wrote:
Fred Zwarts wrote:
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
Jan 25 '06 #6

Victor Bazarov wrote:
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.

Jan 25 '06 #7
Victor Bazarov wrote:
mlimber wrote:
Fred Zwarts wrote:
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

Jan 25 '06 #8
Fred Zwarts wrote:
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
Jan 25 '06 #9
In article <dr**********@info.service.rug.nl>,
"Fred Zwarts" <F.******@KVI.nl> wrote:
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
Jan 26 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

20 posts views Thread by Glenn Venzke | last post: by
reply views Thread by Vaclav Haisman | last post: by
3 posts views Thread by Richard | last post: by
13 posts views Thread by Adam Blair | last post: by
18 posts views Thread by Visual Systems AB \(Martin Arvidsson\) | last post: by
3 posts views Thread by giant food | last post: by
34 posts views Thread by Steven Nagy | last post: by
6 posts views Thread by bsma1 | last post: by
1 post views Thread by jerry | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.