Topic: switch & enum


Author: bill@amber.ssd.csd.harris.com (Bill Leonard)
Date: 1995/07/24
Raw View
In article <3ue8l7$28g@gabi.gabi-soft.fr>, kanze@gabi-soft.fr (J. Kanze) writes:
> I think what he should have said is that for a language with a sensible
> definition of an enumerated type, the only sensible values in the cases
> should be the enumerated values.  Of course, such a statement says
> nothing about what would be sensible values in C or C++.

Nor is it anything more than a bald statement of opinion.  What is
"sensible" to him may not be sensible to me.

> And I would consider it a useful piece of documentation, informing me
> that you meant for the default case to do nothing, rather than just
> having forgotten a value or two:-).

I just don't see much value in that.  I see much more value in not having
useless lines of code to clutter up the program.

> (I sometimes have to compile code I pull in over FTP, and I really
> cannot expect that everyone out there agrees with me as to how a program
> should be written.)

Including me. :-)

> Agreed.  But warnings which can easily be eliminated by clean
> programming practices are fine with me.

But when you're programming as a team, and not everyone on that team agrees
on what practices constitute "clean programming practices", you can get
lots of warnings that are not "easily eliminated".

I very much dislike compilers that try to enforce a particular programming
discipline or style on me.  Certainly some programs are easier to read than
others, but I've seen lots of programs written in widely varying styles
that *were* all easy to read and understand.  I don't believe that any
*one* style is best for everyone.  And enforcement of style just clutters
up the compiler output with useless warnings that obscure the warnings I
should really pay attention to.

--
Bill Leonard
Harris Computer Systems Corporation
2101 W. Cypress Creek Road
Fort Lauderdale, FL  33309
Bill.Leonard@mail.hcsc.com

These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Harris Computer Systems Corporation.

------------------------------------------------------------------------------
More people run Windows on their home computers than on any other home
appliance.
------------------------------------------------------------------------------





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/07/25
Raw View
In article <3v0jpk$5kt@hawk.hcsc.com> bill@amber.ssd.csd.harris.com
(Bill Leonard) writes:

|> But when you're programming as a team, and not everyone on that team agrees
|> on what practices constitute "clean programming practices", you can get
|> lots of warnings that are not "easily eliminated".

More important, even if everyone on the team agrees, if what they
agree to is not what the compiler writer implemented...

On the other hand, warnings are always `easily eliminated', at least
under Unix.  Just pipe the compiler output through grep:-).

|> I very much dislike compilers that try to enforce a particular programming
|> discipline or style on me.  Certainly some programs are easier to read than
|> others, but I've seen lots of programs written in widely varying styles
|> that *were* all easy to read and understand.  I don't believe that any
|> *one* style is best for everyone.  And enforcement of style just clutters
|> up the compiler output with useless warnings that obscure the warnings I
|> should really pay attention to.

We've encountered this a lot.  In fact, following some of our coding
guidelines causes warnings to be generated ("Static variable
...sccs_id defined but not used", for example).  We systematically
pass the compiler output through a shell script which eliminates the
warnings that we have deemed irrelevant.  Our coding guidelines
specify that the code must compile without warnings, but it is in fact
the output of the shell script which should be without warnings (and
an individual coder can always get an exemption for a special case).
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/07/17
Raw View
Bill Leonard (bill@amber.ssd.csd.harris.com) wrote:
|> In article <3s8t5c$3dj@bmdhh222.bnr.ca>, dbinder@bnr.ca (David Binderman) writes:
|> > We reached the opinion that when doing a switch on an enum, the only
|> > sensible values in the cases should be identifiers in the definition
|> > of the enum.

|> I humbly disagree.  I have had occasion to define enums like this:

|>    enum Q (a = 1, b = 2, c = 4, d = 8);

|> and then use values like "a | b", or "a | b | c".  That is, the enumeration
|> values are bit masks and it is perfectly reasonable to OR them together.

|> Now had you said "the only sensible values in the cases should be
|> *expressions* involving only the enum identifiers", I might agree.

I think what he should have said is that for a language with a sensible
definition of an enumerated type, the only sensible values in the cases
should be the enumerated values.  Of course, such a statement says
nothing about what would be sensible values in C or C++.

|> > We also reached the equally amazing conclusion that any values in the
|> > enum, not catered for in the switch, should be a compiler error, not
|> > a warning.

|> This kind of thing can easily be carried too far.  For instance, the C++
|> compiler I use (a cfront derivative) gives a warning on code like this:

|>    enum E {
|>       a,
|>       b,
|>       c,
|>       d
|>    };

|>    E   e;

|>    switch (e) {
|>    case  a:
|>    case  b:
|>    default:
|>    }

|> The warning says something like "4 enumeration values, only 2 cases".
|> Whenever I see this warning I become apoplectic.  What the H*** does the
|> compiler think I put the D*** "default" clause in there for?!?!?!?!

|> Furthermore, the behavior of switch is perfectly well-defined when none of
|> the cases match: do nothing.  That is often what I want to do -- I need
|> some special-case processing for one or two values, and not for the rest.
|> If I *had* to put in a null default clause, I would regard that as a
|> useless requirement that just clutters the code unnecessarily.

And I would consider it a useful piece of documentation, informing me
that you meant for the default case to do nothing, rather than just
having forgotten a value or two:-).

|> So, I would disagree with your assertion that it should be a compiler error.
|> A warning, maybe, but even that can get annoying.

I would not want to see it a compiler error, for the simple reason that
it is legal, and a compiler should not generate an error for legal code.
(I sometimes have to compile code I pull in over FTP, and I really
cannot expect that everyone out there agrees with me as to how a program
should be written.)

|> Finally, I'd like to point out that, once a compiler gets to spewing very
|> many warning messages at me that I routinely ignore, I easily miss warnings
|> I *am* interested in.  Cfront is particularly bad about that, because (like
|> the above case) it warns me about perfectly legitimate usage.  You really
|> can get too many warnings.

Agreed.  But warnings which can easily be eliminated by clean
programming practices are fine with me.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/06/30
Raw View
In article <3ssikb$c6e@hawk.hcsc.com>,
Bill Leonard <Bill.Leonard@mail.csd.harris.com> wrote:
>In article <3s8t5c$3dj@bmdhh222.bnr.ca>, dbinder@bnr.ca (David Binderman) writes:
>> We reached the opinion that when doing a switch on an enum, the only
>> sensible values in the cases should be identifiers in the definition
>> of the enum.
>
>I humbly disagree.  I have had occasion to define enums like this:
>
>   enum Q (a = 1, b = 2, c = 4, d = 8);
>
>and then use values like "a | b", or "a | b | c".  That is, the enumeration
>values are bit masks and it is perfectly reasonable to OR them together.
>

 Try this -- which I recently wrote:

 template<class T1, class T2, class T3> class dunion3 {
 enum {
  s1 = sizeof(T1),
  s2 = sizeof(T2),
  s3 = (s1 > s2 ? s1 : s2),
  s4 = sizeof(T3),
  size = (s3 > s4 ? s3 : s4)
 };
 char buffer[size];
 ...
 };

Here the enum is used purely to factor the computation
of the _constant expression_ required -- this is called
a "regular definition". Its a hack. You can't use
functions here -- constant expressions are required.
Isn't C++ wonderful?

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: bill@amber.ssd.csd.harris.com (Bill Leonard)
Date: 1995/06/28
Raw View
In article <3s8t5c$3dj@bmdhh222.bnr.ca>, dbinder@bnr.ca (David Binderman) writes:
> We reached the opinion that when doing a switch on an enum, the only
> sensible values in the cases should be identifiers in the definition
> of the enum.

I humbly disagree.  I have had occasion to define enums like this:

   enum Q (a = 1, b = 2, c = 4, d = 8);

and then use values like "a | b", or "a | b | c".  That is, the enumeration
values are bit masks and it is perfectly reasonable to OR them together.

Now had you said "the only sensible values in the cases should be
*expressions* involving only the enum identifiers", I might agree.

> We also reached the equally amazing conclusion that any values in the
> enum, not catered for in the switch, should be a compiler error, not
> a warning.

This kind of thing can easily be carried too far.  For instance, the C++
compiler I use (a cfront derivative) gives a warning on code like this:

   enum E {
      a,
      b,
      c,
      d
   };

   E   e;

   switch (e) {
   case  a:
   case  b:
   default:
   }

The warning says something like "4 enumeration values, only 2 cases".
Whenever I see this warning I become apoplectic.  What the H*** does the
compiler think I put the D*** "default" clause in there for?!?!?!?!

Furthermore, the behavior of switch is perfectly well-defined when none of
the cases match: do nothing.  That is often what I want to do -- I need
some special-case processing for one or two values, and not for the rest.
If I *had* to put in a null default clause, I would regard that as a
useless requirement that just clutters the code unnecessarily.

So, I would disagree with your assertion that it should be a compiler error.
A warning, maybe, but even that can get annoying.

Finally, I'd like to point out that, once a compiler gets to spewing very
many warning messages at me that I routinely ignore, I easily miss warnings
I *am* interested in.  Cfront is particularly bad about that, because (like
the above case) it warns me about perfectly legitimate usage.  You really
can get too many warnings.

--
Bill Leonard
Harris Computer Systems Corporation
2101 W. Cypress Creek Road
Fort Lauderdale, FL  33309
Bill.Leonard@mail.hcsc.com

These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Harris Computer Systems Corporation.

------------------------------------------------------------------------------
More people run Windows on their home computers than on any other home
appliance.
------------------------------------------------------------------------------





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/28
Raw View
In article <3sm00r$mv8@bmdhh222.bnr.ca> dbinder@bnr.ca (David
Binderman) writes:

|> Ronald F. Guilmette (rfg@rahul.net) wrote:
|> : In article <3s8t5c$3dj@bmdhh222.bnr.ca>,
|> : David Binderman <dbinder@bnr.ca> wrote:
|> : >hello there,
|> : >
|> : >We've just had some interesting banter about the following code
|> : >
|> : >enum Q { a, b, c};
|> : >
|> : >void f()
|> : >{
|> : > Q w;
|> : > // ...
|> : > switch (w)
|> : > {
|> : > case 1:
|> : >  // ...
|> : > };
|> : >};
|> : >
|> : >We reached the opinion that when doing a switch on an enum, the only
|> : >sensible values in the cases should be identifiers in the definition
|> : >of the enum.

|> : From an esthetic standpoint, yes.  From a practical standpoint, no.

|> How ? Why ?

A simple case, from some of my code:

 enum X
 {
     nothing = 0x00 ,
     a = 0x01 ,
     b = 0x02
 } ;
 X           x ;
 //  ...
 switch ( x )
 {
 //  ...
 case a | b :
     // ...
 }

Under the current rules, this is perfectly legal.  I beleive that
current existing practice also supports such usage, although there are
other ways of writing this.  I would not be particularly surprised,
for example, to see such code in an implementation of ios.

|> : That's totally wrong.  Are you sure that you understand what the
|> : semantics of the following _C_ code are?

|> :  switch (3)
|> :    {
|> :    case 1:
|> :      /* blah blah blah */
|> :      break;
|> :    }

|> The semantics are do nothing. 3 is not the same as 1.

|> Surely all switch statements should have a default, even in the times
|> when that default doesn't do anything. This then gets the programmer
|> to think about what happens when none of the documented cases apply (
|> frequently an internal software error condition, we find).

Surely all C/C++ programs should be cleanly written, and the
programmers should program defensively.  Regretfully, it isn't the
case.  Although I know of no comparable compendium of C++ code, I
invite you to brouse the enormous amount of C code available on the
net, and see just how many of the programs *do* actually program
defensively.  (Just as an example, I have yet to see any C code which
checks the return value of fprintf or fclose, my own excepted, of
course.)

The problem is: if the standards committee starts mandating things
like this, we will break a lot of existing code, which at present sort
of works most of the time.  (For reasons unknown to me, this standard
of quality seems acceptable to most people.)
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: dbinder@bnr.ca (David Binderman)
Date: 1995/06/26
Raw View
Ronald F. Guilmette (rfg@rahul.net) wrote:
: In article <3s8t5c$3dj@bmdhh222.bnr.ca>,
: David Binderman <dbinder@bnr.ca> wrote:
: >hello there,
: >
: >We've just had some interesting banter about the following code
: >
: >enum Q { a, b, c};
: >
: >void f()
: >{
: > Q w;
: > // ...
: > switch (w)
: > {
: > case 1:
: >  // ...
: > };
: >};
: >
: >We reached the opinion that when doing a switch on an enum, the only
: >sensible values in the cases should be identifiers in the definition
: >of the enum.

: From an esthetic standpoint, yes.  From a practical standpoint, no.

How ? Why ?

: That's totally wrong.  Are you sure that you understand what the
: semantics of the following _C_ code are?

:  switch (3)
:    {
:    case 1:
:      /* blah blah blah */
:      break;
:    }

The semantics are do nothing. 3 is not the same as 1.

Surely all switch statements should have a default, even in the times
when that default doesn't do anything. This then gets the programmer
to think about what happens when none of the documented cases apply (
frequently an internal software error condition, we find).


Regards

David C Binderman MSc BSc       dbinder@bnr.co.uk         +44 1628 794 887
Object Oriented Design & Analysis with C++ since 1988
                                                     RIP Plato the fish.





Author: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/06/24
Raw View
In article <3s8t5c$3dj@bmdhh222.bnr.ca>,
David Binderman <dbinder@bnr.ca> wrote:
>hello there,
>
>We've just had some interesting banter about the following code
>
>enum Q { a, b, c};
>
>void f()
>{
> Q w;
> // ...
> switch (w)
> {
> case 1:
>  // ...
> };
>};
>
>We reached the opinion that when doing a switch on an enum, the only
>sensible values in the cases should be identifiers in the definition
>of the enum.



Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/22
Raw View
Steve Clamage (clamage@Eng.Sun.COM) wrote:
|> In article d5j@bmdhh222.bnr.ca, dbinder@bnr.ca (David Binderman) writes:

|> >C++ enums are clearly botched.

|> That depends on what you want from enums. It's hard to find two
|> programmers who entirely agree on what enums should be, and on what
|> constitutes a botched definition.

In this particular case, I think you would find a fair amount of
agreement that, as a language definition for enumerated types, C++ enums
are botched.

There are two answers to this:

1. C++ enum's are C++ enum's, and not an enumerated type.

2. That's a price we pay for evolving from C.

I cannot say that either of these answers are particularly satisfying,
at least intellectually, but practically, the issue of C compatibility
would make me oppose any significant change in the status quo.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: dbinder@bnr.ca (David Binderman)
Date: 1995/06/21
Raw View
hello there,

We've just had some interesting banter about the following code

enum Q { a, b, c};

void f()
{
 Q w;
 // ...
 switch (w)
 {
 case 1:
  // ...
 };
};

We reached the opinion that when doing a switch on an enum, the only
sensible values in the cases should be identifiers in the definition
of the enum.

We also reached the equally amazing conclusion that any values in the
enum, not catered for in the switch, should be a compiler error, not
a warning.

I see nothing in the standard about this, so does it then become a
compiler quality issue ?

Regards

David C Binderman MSc BSc       dbinder@bnr.co.uk         +44 1628 794 887
Object Oriented Design & Analysis with C++ since 1988
                      Code policeman, language lawyer and Purify advocate





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/21
Raw View
In article 3dj@bmdhh222.bnr.ca, dbinder@bnr.ca (David Binderman) writes:
>hello there,
>
>We've just had some interesting banter about the following code
>
>enum Q { a, b, c};
>
>void f()
>{
> Q w;
> // ...
> switch (w)
> {
> case 1:
>  // ...
> };
>};
>
>We reached the opinion that when doing a switch on an enum, the only
>sensible values in the cases should be identifiers in the definition
>of the enum.

"Sensible" is a value judgement. I would agree that using literal integers
for the case labels is probably a bad idea. Code could silently break if
the enumerator values changed. The usage is allowed, however. According
to the draft standard, the switch condition undergoes promotion, and the
values on the case labels are converted to that promoted type.

>We also reached the equally amazing conclusion that any values in the
>enum, not catered for in the switch, should be a compiler error, not
>a warning.

Not allowed by the standard. If any value does not have a corresponding
case label, the 'default' label is taken if there is one, otherwise the
switch is skipped. That has always been the rule in C and C++.

Your proposed interpretation would also be unusable in real code. An enum
type allows any value in the extended range of its enumerators. So given
an enum like
 enum E { lo=-100, hi=999 };
any object of type E may take on any value from -127 (-128 on two's-
complement machines) through +1023. You don't want to be required to supply
all those case labels, do you?
---
Steve Clamage, stephen.clamage@eng.sun.com







Author: dbinder@bnr.ca (David Binderman)
Date: 1995/06/21
Raw View
Thanks for the fast response.

Steve Clamage (clamage@Eng.Sun.COM) wrote:
: In article 3dj@bmdhh222.bnr.ca, dbinder@bnr.ca (David Binderman) writes:
: >hello there,
: >
: >We've just had some interesting banter about the following code
: >
: >enum Q { a, b, c};
: >
: >void f()
: >{
: > Q w;
: > // ...
: > switch (w)
: > {
: > case 1:
: >  // ...
: > };
: >};
: >
: >We reached the opinion that when doing a switch on an enum, the only
: >sensible values in the cases should be identifiers in the definition
: >of the enum.

: "Sensible" is a value judgement. I would agree that using literal integers
: for the case labels is probably a bad idea. Code could silently break if
: the enumerator values changed. The usage is allowed, however. According
: to the draft standard, the switch condition undergoes promotion, and the
: values on the case labels are converted to that promoted type.

So if something is probably a bad idea, then it got to be worth a
compiler warning or an error, or not ?

Consider the folliwing related code

enum Q { a, b, c };

enum K { d, e, f };

void
g()
{
 Q qwe;

 switch (qwe)
 {
 case d:
  ;
 };
};

One popular compiler produced this:

enum.cc: In function `void g()':
enum.cc:15: warning: enumeration value `c' not handled in switch
enum.cc:15: warning: enumeration value `b' not handled in switch

guaranteed to confuse us !

: Your proposed interpretation would also be unusable in real code. An enum
: type allows any value in the extended range of its enumerators. So given
: an enum like
:  enum E { lo=-100, hi=999 };
: any object of type E may take on any value from -127 (-128 on two's-
: complement machines) through +1023. You don't want to be required to supply
: all those case labels, do you?

Clearly not. Your example enum would benefit from a default case for when
an object of type E didn't have one of the values lo or hi.

C++ enums are clearly botched. Oh well. Time to change them all to classes.

Regards

David C Binderman MSc BSc       dbinder@bnr.co.uk         +44 1628 794 887
Object Oriented Design & Analysis with C++ since 1988
                      Code policeman, language lawyer and Purify advocate





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/21
Raw View
In article d5j@bmdhh222.bnr.ca, dbinder@bnr.ca (David Binderman) writes:
>
>: >
>: >We reached the opinion that when doing a switch on an enum, the only
>: >sensible values in the cases should be identifiers in the definition
>: >of the enum.
>
>: "Sensible" is a value judgement. I would agree that using literal integers
>: for the case labels is probably a bad idea. Code could silently break if
>: the enumerator values changed. The usage is allowed, however. According
>: to the draft standard, the switch condition undergoes promotion, and the
>: values on the case labels are converted to that promoted type.
>
>So if something is probably a bad idea, then it got to be worth a
>compiler warning or an error, or not ?

It's a bad idea to have variable names ll1, l1l, l11 in the same function,
or S5S, SS5, S55, or OOO, OO0, O00, for example. Should those be errors too?

"Error" is not really a standards term, but we use it to mean a violation
which must be diagnosed, and which makes the program "ill-formed". A compiler
cannot reject a program unless it is ill-formed. The example code was not
ill-formed, but was in fact well-defined.

The Standard does not address the subject of warnings. A compiler may emit
warnings about anything at all. "Warning: function 'f' has more than 50
lines." "Warning: 'dfxcgxzq' is hard to pronounce." You can lobby your
favorite vendor to add or remove warnings quite apart from what constitutes
valid (well-defined) C++ code.

>C++ enums are clearly botched.

That depends on what you want from enums. It's hard to find two
programmers who entirely agree on what enums should be, and on what
constitutes a botched definition.

---
Steve Clamage, stephen.clamage@eng.sun.com