specifying enumeration size as member: good or bad

N

Neil Zanella

Hello,

I have seen code that does the following:

enum Letter { X, Y, Z, numLetters };

Is this considered good or bad code? On one hand, the code seems more
maintainable because no matter whether letters are added or removed
the value of numLetters will be correct (as long as no letter is
given a number with the equal sign which makes this untrue).

On the other hand, this forces the need for needless default
cases in switch statements since the compiler will complain
if in a switch numLetters above is not taken care of.

So, is this good or bad?

Opinions welcome,

Regards,

Neil
 
M

Mike Wahler

Neil Zanella said:
Hello,

I have seen code that does the following:

enum Letter { X, Y, Z, numLetters };

Is this considered good or bad code? On one hand, the code seems more
maintainable because no matter whether letters are added or removed
the value of numLetters will be correct (as long as no letter is
given a number with the equal sign which makes this untrue).

As long as all the values have sequential values
beginning with zero, as is the default. Some or
all of these values could be explicitly specified
if desired.
On the other hand, this forces the need for needless default
cases in switch statements since the compiler will complain
if in a switch numLetters above is not taken care of.

What do you mean? It needs no 'taking care of'.
A 'switch' statement will only do what you tell
it to with particular values, and nothing with
others. What error message are you getting,
with what specific code?

enum Letter value = Y;


switch(value)
{
case X:
/* whatever */
break;
}

Note that only one value is processed by the switch.
This should not result in a compiler error.
So, is this good or bad?

Using 'one more' value in a list of sequential enumeration
values is sometimes used to maintain a 'count' of the
values, yes. Whether it's 'good' or 'bad' really depends
upon what you're doing.

-Mike
 
C

Claudio Puviani

Neil Zanella said:
Hello,

I have seen code that does the following:

enum Letter { X, Y, Z, numLetters };

Is this considered good or bad code?

I consider it to be bad because it breaks the cohesion of the type. The type
'letter' now represents two separate concepts: letters AND the number of
possible letters. If you had a set (in the generic sense, not the standard
container) of letters, this type indicates that the set could contain
'numLetters' as a valid member, which is completely absurd. 'numLetters'
should be a separate constant. Both the enum and the constant -- along with
various utility functions -- could be kept in a common namespace or class if
they need to be packaged together, but never in the same enum.
On one hand, the code seems more maintainable because
no matter whether letters are added or removed the value
of numLetters will be correct (as long as no letter is
given a number with the equal sign which makes this untrue).

It's a lot more maintainable to change one constant if the enum is changed
than to track down errors because the enum is incorrectly designed.
On the other hand, this forces the need for needless default
cases in switch statements since the compiler will complain
if in a switch numLetters above is not taken care of.

At the very least.
So, is this good or bad?

Definitely bad.

Claudio Puviani
 
N

Nick Hounsome

Neil Zanella said:
Hello,

I have seen code that does the following:

enum Letter { X, Y, Z, numLetters };

Is this considered good or bad code? On one hand, the code seems more
maintainable because no matter whether letters are added or removed
the value of numLetters will be correct (as long as no letter is
given a number with the equal sign which makes this untrue).

On the other hand, this forces the need for needless default
cases in switch statements since the compiler will complain
if in a switch numLetters above is not taken care of.

So, is this good or bad?

Bad because:
void foo(Letter);

foo(numLetters); // OK?

Also many compilers will issue a warning if you create a switch(Letter)
statement that includes
neither numLetters nor a default case.

A better variation (for the usual enums without initializers) is:
enum Letter { X, Y, Z, FIRST_LETTER=X, LAST_LETTER=Z };
This way you don't introduce a value that is outside the proper range and
FIRST_LETTER is sometimes useful when you want to pass them as ints and
use 0 as an undefined value (if you init X=1)
 
R

Richard Herring

Claudio said:
I consider it to be bad because it breaks the cohesion of the type. The type
'letter' now represents two separate concepts: letters AND the number of
possible letters.

But number-of-letters is just a way of thinking. Rename the extra item:

enum Letter { X, Y, Z, endOfLetters };

Now it's just an example of the all-pervasive C++ one-past-the-end
paradigm.
If you had a set (in the generic sense, not the standard
container) of letters, this type indicates that the set could contain
'numLetters' as a valid member, which is completely absurd.

'numLetters'
should be a separate constant. Both the enum and the constant -- along with
various utility functions -- could be kept in a common namespace or class if
they need to be packaged together, but never in the same enum.


It's a lot more maintainable to change one constant if the enum is changed

Even more maintainable not to have to change anything else...
than to track down errors because the enum is incorrectly designed.

If you consider that to be an incorrect design, of course ;-)
At the very least.

But not all enums are used in switches.
Definitely bad.
_Sometimes_ bad.
 

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

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top