Topic: proposal: enhancing SWITCH type checking for enums


Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 12 Mar 2003 18:47:22 +0000 (UTC)
Raw View
In article <87r89himbj.fsf@Astalo.kon.iki.fi>, Kalle Olavi Niemitalo
<kon@iki.fi> writes
>francis.glassborow@ntlworld.com (Francis Glassborow) writes:
>
>> IOWs I want enums to be a little closer to classes. I would also like to
>> give serious consideration to supplying them with built-in bitwise
>> operators (those are the commonest operators people wish to apply to
>> them).
>
>Can you make this type-safe:
>
>  enum E { A = 1, B = 2, C = 4 };
>  E f();
>  E e = f() & ~A;
>
>Operators & | ^ &= |= ^= are not a problem but the complement is.
>If you define ~A as E(6), that is a silently incompatible change.

A good point but one that could be dealt with by defining what operator
~ would do in the context of an enum.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kon@iki.fi (Kalle Olavi Niemitalo)
Date: Sun, 9 Mar 2003 05:28:14 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> IOWs I want enums to be a little closer to classes. I would also like to
> give serious consideration to supplying them with built-in bitwise
> operators (those are the commonest operators people wish to apply to
> them).

Can you make this type-safe:

  enum E { A = 1, B = 2, C = 4 };
  E f();
  E e = f() & ~A;

Operators & | ^ &= |= ^= are not a problem but the complement is.
If you define ~A as E(6), that is a silently incompatible change.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: lvr@softsystem.co.uk ("Lawrence Rust")
Date: Wed, 5 Mar 2003 17:41:02 +0000 (UTC)
Raw View
"Allan W" wrote...
> And what would happen when this error was detected at runtime?
> Throw an exception?
>
>    bool isprime(int i) {
>        enum primes { p1=2, p2=3, p3=5, p4=7, p5=11,
>                      p6=13, p7=17, p8=19, p9=23,
>                      // ... you get the idea
>                    };
>        try {
>           primes p(i);
>           return true; // If we could construct it, it's prime
>        } catch(...) { return false; }
>    }
>
> If we can construct p, that proves i is prime...?

An exception seems like a good idea.  However, as it stands it could break
significant amounts of code.  What's really needed is a hint to the compiler
that the set is closed.  This might usefully be indicated by adding an
'explicit' prefix to the enum declaration.  Say:

explicit enum primes { ... };

-- Lawrence Rust, Software Systems, www.softsystem.co.uk

The problem with Windows XP: http://www.arachnoid.com/boycott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 6 Mar 2003 00:05:00 +0000 (UTC)
Raw View
> "Allan W" wrote...
> > And what would happen when this error was detected at runtime?
> > Throw an exception?

lvr@softsystem.co.uk ("Lawrence Rust") wrote
> An exception seems like a good idea.

Not to me, it doesn't.

1. Programs would now have to handle a new type of exception that they
didn't previously know about.  This could conceivably affect every
line of code in the application!

2. The run-time implications are too startling. Currently, any given
integer size either "fits" into the enum's underlying type, or else
it doesn't (and we truncate). So converting any integer type into an
enum type is about as complicated as a reinterpret_cast.

If the definition of enums changes to allow only specific values,
this would change dramatically. Now the compiler would have to
search through a table of all legal values for an enum, to see if
this new value was present. This would be required for ANY assignment
to enums -- possibly excluding copy assignment. Compiled code would
bloat.

We could mitigate this by saying that the compiler would only check
assignment for enums that have values in a closed range starting at 0,
or (almost equivalently) only in enums where none of the enum-constants
have had specific values formed (i.e. the enum type is declared without
any equal signs). Then the compiler could just compare the new value of
an enum to the maximum. But this is still about twice as much code as
we need today.

> However, as it stands it could break
> significant amounts of code.

Sure could!

> What's really needed is a hint to the compiler
> that the set is closed.  This might usefully be indicated by adding an
> 'explicit' prefix to the enum declaration.  Say:
>
> explicit enum primes { ... };

If we must trap invalid enum values, this is the way to do it.
But I still worry that it will cause more problems than it prevents.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 5 Mar 2003 03:01:24 +0000 (UTC)
Raw View
rmaddox@isicns.com (Randy Maddox) wrote
> Since the compiler knows what that set of
> values is it would seem more useful to me for the compiler to more
> strictly enforce that only those values may be used.  In other words,
> rather than having the above result in an unspecified value if 1 is
> not in the range of enumerated values I would much prefer that to be
> defined to be an error since that would let us rely more firmly on the
> assumption that a value of an enum type would actually contain only
> one of those enumerated values.

And what would happen when this error was detected at runtime?
Throw an exception?

   bool isprime(int i) {
       enum primes { p1=2, p2=3, p3=5, p4=7, p5=11,
                     p6=13, p7=17, p8=19, p9=23,
                     // ... you get the idea
                   };
       try {
          primes p(i);
          return true; // If we could construct it, it's prime
       } catch(...) { return false; }
   }

If we can construct p, that proves i is prime...?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Mon, 24 Feb 2003 19:56:17 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<1045838379.568224@master.nyc.kbcfp.com>...
> danielgutson@hotmail.com wrote:
> >  I'd like to see your feedback about this proposal.
>
> It's wrong. Enumeration variables can hold values
> which are not any of the literals. Enumerations
> are specified by the standard in a way that permits
> enumeration literals to be used as bitmask items,
[snip]

I don   t know if I understood you correctly.

If you say that

enum E { a,b,c};

then E e = 1;

works, I   m afraid it   s not correct. (it is in C, but not in C++).

Even
E e = E(-1)
 I think is unspecified behavior (don   t have the std. here, but I
think I read it in the Stroustrup   s book).
If it IS correct, then it should be denied.
(there are some texts referring that bitmasks should be treated
different:

enum BMasks
{
   m1 = 0x0001,
   m2 = 0x0010,
   m3 = 0x0100,
   m4 = 0x1000
};

then the values ored (or anded) should not be declared as BMasks:

unsigned int Result = m1 | m2;

as far as the Result is not a bitmask, but a result of operating
between them.
)

 Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: Mon, 24 Feb 2003 19:56:20 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<Jtnj9nBvIhV+Ew6E@robinton.demon.co.uk>...
> In article <23478c42.0302201425.1e321944@posting.google.com>,
> "danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
> >RULES.
> > Whenever a switch statement receives an enum type, the case labels
> >should have the enum elements only.
>
> This would break existing code and in my judgement without sufficient
> compensatory benefit.
>
> >IF:
> >  1) a case label is not, it means an error.
> >  2) the case expressions don't cover all the enum members, and:
> >    2.1) there's no DEFAULT label, a warning should be thrown.
> >    2.2) there's a DEFAULT label, no warning is thrown, but (I think)
>
> There is no mechanism within the C++ standard to require warnings. All
> we can require is a diagnostic for ill-formed code.

IIRC, it is well-defined to have an unreachable case. We could make it
undefined, no diagnostic required, to have a label that cannot be
reached because it is bigger than any possible value of the underlyiong
enum. That doesn't impact conforming compilers, but it could impact
(legal) existing programs that "used" unreachable code.

Do we want this? I'm not convinced; I'd probably say no.

--
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Mon, 24 Feb 2003 20:10:24 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<Jtnj9nBvIhV+Ew6E@robinton.demon.co.uk>...
> In article <23478c42.0302201425.1e321944@posting.google.com>,
> "danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
> >RULES.
> > Whenever a switch statement receives an enum type, the case labels
> >should have the enum elements only.
>
> This would break existing code and in my judgement without sufficient
> compensatory benefit.

Yes, I ommitted the    Compatibility    section in my original message,
sorry about that.
But I agree (to break existing code), and let me tell you why:

1) it forces re-viewing the situations that could be ill-formed.
For example, in my last project, I inherited a legacy code that had
bugs on some switchs because of this. It would be great to be    warned
(I would prefer    forced   ) to review those places where switchs are
doing strange things with enums.
2) In [at least my] experience, switches are more often used with
enums that magic (or orfan) values. (by orfan I mean constants,
literals, etc.), such as error codes, command codes, etc.
3) Even the change would be extremely simple (for an    emergency
porting :) ),
simply by casting the enum to an int in the switch would disable the
feature:
  switch(color)
to
  switch((int)color)

where color is of enum type.

>
> >IF:
> >  1) a case label is not, it means an error.
> >  2) the case expressions don't cover all the enum members, and:
> >    2.1) there's no DEFAULT label, a warning should be thrown.
> >    2.2) there's a DEFAULT label, no warning is thrown, but (I think)
>
> There is no mechanism within the C++ standard to require warnings. All
> we can require is a diagnostic for ill-formed code.

Yes, I know, and I wasn   t clear enough. It should be read as    the
compiler should...   , but the important thing is that this would enable
the implementation to throw such warning.
(Ok, the warning could be done already without this, but, it would be
coherent with the forced behavior of type checking).

>
> >a good practice would be avoiding DEFAULT labels for switch on enums
> >and expliciting all the enum values. This would help mainteinance when
> >the enum grows and we want that all the values are considered.
>
> That is a matter of opinion. I already have, IMHO, well designed and
> well written code that uses enums and default cases.

Agree, that   s why I said that that would be a good practice :) (In
fact, I had a function for a state machine that accepted only 3 of the
18 possible stimulus! In that case, I used a    default    :) ). But, if
possible, I still think that for small number of values, a default
should be avoided.
(out of this thread   s scope, again agree).

> Like, I suspect, many others, I use enums for the purpose of making my
> code self documenting. I suspect that the number of places where the
> control variable is of enum type is relatively rare but not non-existent
> which is why there is a problem with legacy code.

Well, as I wrote above, it   s inverted respect of the situations I saw
(I will search some publications if anybody ever counted some stats
about switch usage and enums).

>
> If we are going to consider enhancing the functionality of switch, I
> think we must first tackle the general issue of literals (perhaps taking
> a look at C99's compound literals). This is a tough problem even though
> solving it might allow switch on such things as string literals.
>
Actually, I admit that I ignore why    switch    only allow constant
expressions.
(is this what are you talking about?)

I   m preparing a paper (the one I mention to Philippe about enums)
where I propose to analyze the possibility of overloading the switch
statement. But we are too far from that yet :)

 Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Mon, 24 Feb 2003 20:10:26 +0000 (UTC)
Raw View
philippe_mori@hotmail.com ("Philippe Mori") wrote in message news:<Miv5a.5843$hv3.559197@news20.bellglobal.com>...

> Maybe it would also be interesting to allows enumeration
> extension:
>
> enum Der : enum Base { /* some extra values here */ };
[snip]

Hi Philippe:

 I smiled when read your comment :)  This is my 4th month writing a
paper for enhancing enums. I will publish it in TOPLAS, ACM.
I stopped writing it for these [more basic] proposals, and hope it
will be ready for the second meeting of the committee.
What I   m writing is a redefinition of the enum keyword of C++,
accepting inheritance, non-integral underlying types, and    enumeration
of classes   . If you want, I   ll send you the draft in May (or April,
but after the meeting), and I   ll be glad to have your feedback.
I   m gathering some info, what exist in other languages, and how the
type-system is enhanced with this (I   m messing with some formal
typed-lambda proofs stuff :( ).
SUN proposed something for Java. Many languages have the first two
features (inheritance and non-integral und. type), but enum of classes
is a novel concept so far.
Cardelli mentions something about enum inheritance, and it   s a bit
complex to formally treat because it   s supertyping instead of
subtyping.
(when you say extendedColors : colors, you will always be able to cast
from colors to extendedColors, but not viceversa).

Let me finnish and share with you! :)

>
> Also it would be interesting to be able to have some informations
> on enumerated values (min, max, complete between min and max,...)
> It would then be possible for example to do ranges between limits.

also contempled :)

> Another thing that I like more or less with enumeration is the
> fact that doing e++, ++e, e1 | e2 do not give an enumerated type
> without overloadding operators for the enumerated type...

I also thought about that: I have such problem every day when dealing
with bitmasks. (bitwise operations with enums)
And that issue is solved in the approach, by enumerating classes.

--some examples:

class Vector2D { ... };

Vector2D enum Directions
{
  Up(1,0),
  Dn(-1,0),
  Lf(0,1),
  Rt(0,-1)
};

enum ExtendedDirections : Directions
{
  UpLf(1,1),
  ...
};

But please let   s talk about this after April! :)

 Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 24 Feb 2003 21:39:47 +0000 (UTC)
Raw View
In article <23478c42.0302241007.61ac6416@posting.google.com>,=20
"danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
>I=B4m preparing a paper (the one I mention to Philippe about enums)
>where I propose to analyze the possibility of overloading the switch
>statement. But we are too far from that yet :)

If you want it to be seriously considered for the next version of C++=20
you need to get a move on. It is extensive with serious impact and so=20
needs early consideration. You will also need at least one very=20
competent supporter on the Standards Committee, preferably one with an=20
existing reputation and track record.


--=20
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 24 Feb 2003 22:43:46 +0000 (UTC)
Raw View
In article <23478c42.0302241014.51ee4361@posting.google.com>,=20
"danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
>hyrosen@mail.com (Hyman Rosen) wrote in message news:<1045838379.568224@=
master.nyc.kbcfp.com>...
>> danielgutson@hotmail.com wrote:
>> >  I'd like to see your feedback about this proposal.
>>
>> It's wrong. Enumeration variables can hold values
>> which are not any of the literals. Enumerations
>> are specified by the standard in a way that permits
>> enumeration literals to be used as bitmask items,
>[snip]
>
>I don=B4t know if I understood you correctly.
>
>If you say that
>
>enum E { a,b,c};
>
>then E e =3D 1;
>
>works, I=B4m afraid it=B4s not correct. (it is in C, but not in C++).

Because C++ does not provide implicit conversion form int to enum.=20
However:

E e(1);

works. (which is yet more evidence for my preference for function style=20
initialisers :-)

>
>Even
>E e =3D E(-1)
> I think is unspecified behavior (don=B4t have the std. here, but I
>think I read it in the Stroustrup=B4s book).

In the Standard 7.2 para 9, but I am a little unhappy with the use of=20
unspecified in this context because I think it should probably be=20
undefined.

>If it IS correct, then it should be denied.
>(there are some texts referring that bitmasks should be treated
>different:

No the standard explicitly gives the range in terms of bits so oring=20
enum enumerations must result in a value in the permitted range of the=20
underlying integer type.

>
>enum BMasks
>{
>   m1 =3D 0x0001,
>   m2 =3D 0x0010,
>   m3 =3D 0x0100,
>   m4 =3D 0x1000
>};
>
>then the values ored (or anded) should not be declared as BMasks:
>
>unsigned int Result =3D m1 | m2;
>
>as far as the Result is not a bitmask, but a result of operating
>between them.

I am not sure what you mean. BMask( m1 | m2 ) has a defined meaning.

>)
>

--=20
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: algrant@myrealbox.com (Al Grant)
Date: Tue, 25 Feb 2003 16:24:02 CST
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<C3aBrINWIoW+Ewzr@robinton.demon.co.uk>...
> In article <23478c42.0302241014.51ee4361@posting.google.com>,
> "danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
> >If you say that
> >enum E { a,b,c};
> >then E e = 1;
> >works, I m afraid it s not correct. (it is in C, but not in C++).
>
> Because C++ does not provide implicit conversion form int to enum.
> However:
> E e(1);
> works.

No it doesn't!

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Tue, 25 Feb 2003 23:55:18 +0000 (UTC)
Raw View
In article <5765b025.0302251015.69e467c3@posting.google.com>, Al Grant
<algrant@myrealbox.com> writes
>> Because C++ does not provide implicit conversion form int to enum.
>> However:
>> E e(1);
>> works.
>
>No it doesn't!

You are right :( I should look things up :) However it is, IMHO,
blatantly obvious that it should work as this is initialisation not
assignment.

Can anyone give a reason why this wart should not be removed in a future
release of C++?


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: algrant@myrealbox.com (Al Grant)
Date: Wed, 26 Feb 2003 17:41:52 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<FFqgn4aUz$W+Ewhv@robinton.demon.co.uk>...
> In article <5765b025.0302251015.69e467c3@posting.google.com>, Al Grant
> <algrant@myrealbox.com> writes
> >> Because C++ does not provide implicit conversion form int to enum.
> >> However:
> >> E e(1);
> >> works.
> >
> >No it doesn't!
>
> You are right :( I should look things up :) However it is, IMHO,
> blatantly obvious that it should work as this is initialisation not
> assignment.

But the initialization-written-like-assignment case
  E e = 1;
doesn't work either.  Or do you want them both to be legal?

It is blatantly obvious that passing an integer to a function
taking an enum argument should not work.  First, it is defined to
be like assignment, and second, you probably don't want implicit
conversion there.  It would be confusing to have a different rule
when the constructor syntax is used for initialization.

The rule for assignment, initialization etc. seems perfectly
adequate here, certainly the cause of the problem is not that,
or even implicit conversion from enum to int, but promotion
from enum to int.  It would be interesting to see how much
source would compile with that promotion turned off (and the
bitwise and addition operators available as functions on enums).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Wed, 26 Feb 2003 18:24:45 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<FFqgn4aUz$W+Ewhv@robinton.demon.co.uk>...
> In article <5765b025.0302251015.69e467c3@posting.google.com>, Al Grant
> <algrant@myrealbox.com> writes
> >> Because C++ does not provide implicit conversion form int to enum.
> >> However:
> >> E e(1);
> >> works.
> >
> >No it doesn't!
>
> You are right :( I should look things up :) However it is, IMHO,
> blatantly obvious that it should work as this is initialisation not
> assignment.
>
> Can anyone give a reason why this wart should not be removed in a future
> release of C++?
>
>
> --
> ACCU Spring Conference 2003 April 2-5
> The Conference you cannot afford to miss
> Check the details: http://www.accuconference.co.uk/
> Francis Glassborow      ACCU
>

It appears from 7.2/9 that the following should compile:

  E e(E(1));

But the value of e is unspecified if 1 is not in the range of values
enumerated for E.  My personal feeling is that this is a big hole in
use of enums since the point of an enum is to be able to define a set
of specific, named values.  Since the compiler knows what that set of
values is it would seem more useful to me for the compiler to more
strictly enforce that only those values may be used.  In other words,
rather than having the above result in an unspecified value if 1 is
not in the range of enumerated values I would much prefer that to be
defined to be an error since that would let us rely more firmly on the
assumption that a value of an enum type would actually contain only
one of those enumerated values.

Of course making this an error would break some existing code, but
OTOH if that code is getting values outside the enumerated range is it
not already at least logically broken?

I like enums and use them frequently, but I would be a lot more
comfortable if I could count on the compiler to more strictly enforce
the logical concept of the enumeration.

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sdouglass@arm.com (scott douglass)
Date: Wed, 26 Feb 2003 22:08:24 +0000 (UTC)
Raw View
enum E { A = 1, B = 2, C = 4 };

Francis Glassborow wrote:
>>> Because C++ does not provide implicit conversion form int to enum.
>>> However:
>>> E e(1);
>>> works.

> In article <5765b025.0302251015.69e467c3@posting.google.com>, Al Grant
> <algrant@myrealbox.com> writes
>> No it doesn't!

Francis Glassborow wrote:
> You are right :( I should look things up :) However it is, IMHO,
> blatantly obvious that it should work as this is initialisation not
> assignment.
>
> Can anyone give a reason why this wart should not be removed in a future
> release of C++?

Because it's not type-safe.  Do you want the following to work?

  int f();
  E e2(f());

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 27 Feb 2003 05:16:30 +0000 (UTC)
Raw View
In article <5765b025.0302260104.a34008f@posting.google.com>, Al Grant
<algrant@myrealbox.com> writes
>But the initialization-written-like-assignment case
>  E e = 1;
>doesn't work either.  Or do you want them both to be legal?
>
>It is blatantly obvious that passing an integer to a function
>taking an enum argument should not work.  First, it is defined to
>be like assignment, and second, you probably don't want implicit
>conversion there.  It would be confusing to have a different rule
>when the constructor syntax is used for initialization.

I disagree. We already have exactly that difference with ctors that have
been declared as explicit. All I am suggesting is that initialisation of
an enum should like the case of using an explicit ctor, rather than the
equivalence of a copy ctor.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: loic.actarus.joly@wanadoo.fr (=?ISO-8859-1?Q?Lo=EFc_Joly?=)
Date: Thu, 27 Feb 2003 05:16:33 +0000 (UTC)
Raw View
Randy Maddox wrote:

> It appears from 7.2/9 that the following should compile:
>=20
>   E e(E(1));
>=20
> But the value of e is unspecified if 1 is not in the range of values
> enumerated for E.  My personal feeling is that this is a big hole in
> use of enums since the point of an enum is to be able to define a set
> of specific, named values.  Since the compiler knows what that set of
> values is it would seem more useful to me for the compiler to more
> strictly enforce that only those values may be used.  In other words,
> rather than having the above result in an unspecified value if 1 is
> not in the range of enumerated values I would much prefer that to be
> defined to be an error since that would let us rely more firmly on the
> assumption that a value of an enum type would actually contain only
> one of those enumerated values.

What kind of error ? I guess compile time errors are not feasible here,=20
and run-time errors can be quite costly to detect for each assignment,=20
especially if the enum values are not contiguous...

--=20
Lo=EFc

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 27 Feb 2003 16:42:47 +0000 (UTC)
Raw View
In article <b3iobj$anc$1@cam-news1.cambridge.arm.com>, scott douglass
<sdouglass@arm.com> writes
>enum E { A = 1, B = 2, C = 4 };
>
>Francis Glassborow wrote:
>>>> Because C++ does not provide implicit conversion form int to enum.
>>>> However:
>>>> E e(1);
>>>> works.
>
>> In article <5765b025.0302251015.69e467c3@posting.google.com>, Al Grant
>> <algrant@myrealbox.com> writes
>>> No it doesn't!
>
>Francis Glassborow wrote:
>> You are right :( I should look things up :) However it is, IMHO,
>> blatantly obvious that it should work as this is initialisation not
>> assignment.
>>
>> Can anyone give a reason why this wart should not be removed in a future
>> release of C++?
>
>Because it's not type-safe.  Do you want the following to work?
>
>  int f();
>  E e2(f());

Yes, just as it would were E a class the a ctor:
        explicit E(int);
OTOH I do not want:

E e3 = f();

to work (just as it would not if E were a class and either the copy ctor
were inaccessible or the E(int) were declared as explicit.

IOWs I want enums to be a little closer to classes. I would also like to
give serious consideration to supplying them with built-in bitwise
operators (those are the commonest operators people wish to apply to
them). As I understand it:

E e = A;  // OK
e = B & C; // fails unless E operator &(E lhs, E rhs); has been defined

I am happy that

e = B + C;

should fail because arithmetic on enums can push the result outside the
range of supported values but the Standard has carefully ensured that
bitwise operations on enums do not do that.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: algrant@myrealbox.com (Al Grant)
Date: Thu, 27 Feb 2003 21:23:24 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<A+9RZVBNNSX+Ew6g@robinton.demon.co.uk>...
> I disagree. We already have exactly that difference with ctors that have
> been declared as explicit. All I am suggesting is that initialisation of
> an enum should like the case of using an explicit ctor, rather than the
> equivalence of a copy ctor.

I think I see what you are getting at - you mean because you can
write a function-style cast E(1) you should be able to write E e(1).
I think it would make more sense, and be safer, to invalidate
function-style cast in this case on the basis that a function call
(to a constructor or otherwise) would be invalid.  Consider
  enum E { a, b };
  struct S { S(E e) {} };
  ...
  E e = E(1);    // #1
  S s = S(1);    // #2
The fact that #1 is legal when #2 is not is an inconsistency.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Thu, 20 Feb 2003 22:57:21 +0000 (UTC)
Raw View
Hello.

 I'd like to see your feedback about this proposal.

OVERVIEW
 Today, switch statement's parameter is casted to an integral type,
loosing the type information.
This permits the usage of whatever constant expression casteable to
integral in the case labels.

MOTIVATION
 Despite 'switch' statement usage is motive of discussion for object
oriented languages, it is very useful for some situations, is still
wide used, and indeed is part of the language.
The idea of this proposal is to extend the typechecking of the switch
parameter to the case label expressions for enum types.
This prevents the misuse of the constants.
It also enable the existance of a warning when not all the enum values
are present in the switch body (except when a 'default' case wouid be
present) (please see RULES below).
It has no meaning that a switch receiving an enunm value contains a
non-enum constant expression in a case, as far as it should be never
be reached (if the value is not present in the enum), or is covered by
an enum element. This clearly would represent a (typing? conceptual?)
error.

RULES.
 Whenever a switch statement receives an enum type, the case labels
should have the enum elements only.
IF:
  1) a case label is not, it means an error.
  2) the case expressions don't cover all the enum members, and:
    2.1) there's no DEFAULT label, a warning should be thrown.
    2.2) there's a DEFAULT label, no warning is thrown, but (I think)
a good practice would be avoiding DEFAULT labels for switch on enums
and expliciting all the enum values. This would help mainteinance when
the enum grows and we want that all the values are considered.

EXAMPLE.
 enum Colors { Red, Green, Blue };
 const int Blah = 1;

 Colors c = Red;
 switch(c)
 {
   case Red: ...;
   case Green: ...;
   case Blah: ...;     //ERROR
   case 2: ...;        //ERROR
 }

and, would also throw a warning because Colors is not completely
covered (Blue is missing).

Thanks!
  Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dsp@bdal.de (Daniel Spangenberg)
Date: Fri, 21 Feb 2003 15:48:15 +0000 (UTC)
Raw View
Hello Daniel Gutson!

"danielgutson@hotmail.com" schrieb:

> Hello.
>
>  I'd like to see your feedback about this proposal.
>

[snip]

Your partioning of your posting is very fine! Maybe I should learn from it (I
made the experience, that my posting concerning fundamental flaws have not
been answered or only very minorly)


>  Whenever a switch statement receives an enum type, the case labels
> should have the enum elements only.
> IF:
>   1) a case label is not, it means an error.

  Yeah, I think also. The nice thing is, that the following code will also
(and needs to) work:

   enum MyEnum { one, two };

   MyEnum value = ...;  // Whatever

   switch (value)
   {
   case 3: // Error!
    ...
    break;
   case static_cast<MyEnum>(4): // OK, we know what we do!
    ...
    break;
   }


>
>   2) the case expressions don't cover all the enum members, and:
>     2.1) there's no DEFAULT label, a warning should be thrown.
>     2.2) there's a DEFAULT label, no warning is thrown, but (I think)
> a good practice would be avoiding DEFAULT labels for switch on enums
> and expliciting all the enum values. This would help mainteinance when
> the enum grows and we want that all the values are considered.

For short enum definitions this will be feasible, but not for longer ones.
For those cases it would be nice, if C/C++ would provide something like
PASCALS's enumeration ranges in case switches:

   enum MyEnum2 { one, two, three, four,
    ...
    onehundred_ninetynine, twohundred };

  MyEnum2 value = ...; // Whatever

   switch (value)
   {
   case two, ,onehundred: // Pseudocode! Pascalian's would write "case
two..onehundred" of course ;-))
    ...
    break;
   case onehundred, ,twohundred: // Pseudocode!
    break;
   }


Yours

Daniel Spangenberg



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Fri, 21 Feb 2003 20:32:52 +0000 (UTC)
Raw View
danielgutson@hotmail.com wrote:
> Hello.
>
>  I'd like to see your feedback about this proposal.
>
> OVERVIEW
>  Today, switch statement's parameter is casted to an integral type,
> loosing the type information.
> This permits the usage of whatever constant expression casteable to
> integral in the case labels.

    Enums in C and C++ don't carry the implication of the
Pascal/Ada family languages that those are the only possible
values.  This is arguably unfortunate, but standard.

    John Nagle
    Animats

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Fri, 21 Feb 2003 20:33:29 +0000 (UTC)
Raw View
In article <23478c42.0302201425.1e321944@posting.google.com>,
"danielgutson@hotmail.com" <danielgutson@hotmail.com> writes
>RULES.
> Whenever a switch statement receives an enum type, the case labels
>should have the enum elements only.

This would break existing code and in my judgement without sufficient
compensatory benefit.

>IF:
>  1) a case label is not, it means an error.
>  2) the case expressions don't cover all the enum members, and:
>    2.1) there's no DEFAULT label, a warning should be thrown.
>    2.2) there's a DEFAULT label, no warning is thrown, but (I think)

There is no mechanism within the C++ standard to require warnings. All
we can require is a diagnostic for ill-formed code.

>a good practice would be avoiding DEFAULT labels for switch on enums
>and expliciting all the enum values. This would help mainteinance when
>the enum grows and we want that all the values are considered.

That is a matter of opinion. I already have, IMHO, well designed and
well written code that uses enums and default cases.

Like, I suspect, many others, I use enums for the purpose of making my
code self documenting. I suspect that the number of places where the
control variable is of enum type is relatively rare but not non-existent
which is why there is a problem with legacy code.

If we are going to consider enhancing the functionality of switch, I
think we must first tackle the general issue of literals (perhaps taking
a look at C99's compound literals). This is a tough problem even though
solving it might allow switch on such things as string literals.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 21 Feb 2003 20:33:41 +0000 (UTC)
Raw View
danielgutson@hotmail.com wrote:
>  I'd like to see your feedback about this proposal.

It's wrong. Enumeration variables can hold values
which are not any of the literals. Enumerations
are specified by the standard in a way that permits
enumeration literals to be used as bitmask items,
and a variable of an enumeration type can legally
hold any ORed together set of literals, or zero.

     enum E { A = 1, B = 2, C = 4 };
     E e[] = { E(0), E(A|B), E(A|B|C) };

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: philippe_mori@hotmail.com ("Philippe Mori")
Date: Fri, 21 Feb 2003 20:34:48 +0000 (UTC)
Raw View
"Daniel Spangenberg" <dsp@bdal.de> a    crit dans le message news:
3E55FBBC.8260F496@bdal.de...
> Hello Daniel Gutson!
>
> "danielgutson@hotmail.com" schrieb:
>
> > Hello.
> >
> >  I'd like to see your feedback about this proposal.
> >
>
> [snip]
>
> Your partioning of your posting is very fine! Maybe I should learn from it
(I
> made the experience, that my posting concerning fundamental flaws have not
> been answered or only very minorly)
>
>
> >  Whenever a switch statement receives an enum type, the case labels
> > should have the enum elements only.
> > IF:
> >   1) a case label is not, it means an error.
>
>   Yeah, I think also. The nice thing is, that the following code will also
> (and needs to) work:
>
>    enum MyEnum { one, two };
>
>    MyEnum value = ...;  // Whatever
>
>    switch (value)
>    {
>    case 3: // Error!
>     ...
>     break;
>    case static_cast<MyEnum>(4): // OK, we know what we do!
>     ...
>     break;
>    }
>

Or you may force the conversion from enumeration to int in your
switch clauses if you ever need values that are not enumerated...

    switch (value * 1)

But then you still have the problem that it is possible to uses
enumerated values that come from another enumerated type.
Both I think, it is not so bad. In normal case, you should add
missing values to the enumeration so that every values that are
used by a case would be usable in the switch...

Maybe it would also be interesting to allows enumeration
extension:

enum Der : enum Base { /* some extra values here */ };

and you would then be able to uses that extended enum when
you need it...

>
> >
> >   2) the case expressions don't cover all the enum members, and:
> >     2.1) there's no DEFAULT label, a warning should be thrown.
> >     2.2) there's a DEFAULT label, no warning is thrown, but (I think)
> > a good practice would be avoiding DEFAULT labels for switch on enums
> > and expliciting all the enum values. This would help mainteinance when
> > the enum grows and we want that all the values are considered.
>
> For short enum definitions this will be feasible, but not for longer ones.
> For those cases it would be nice, if C/C++ would provide something like
> PASCALS's enumeration ranges in case switches:
>
>    enum MyEnum2 { one, two, three, four,
>     ...
>     onehundred_ninetynine, twohundred };
>
>   MyEnum2 value = ...; // Whatever
>
>    switch (value)
>    {
>    case two, ,onehundred: // Pseudocode! Pascalian's would write "case
> two..onehundred" of course ;-))
>     ...
>     break;
>    case onehundred, ,twohundred: // Pseudocode!
>     break;
>    }
>

Also it would be interesting to be able to have some informations
on enumerated values (min, max, complete between min and max,...)
It would then be possible for example to do ranges between limits.

>
> Yours
>
> Daniel Spangenberg
>
>
>

Another thing that I like more or less with enumeration is the
fact that doing e++, ++e, e1 | e2 do not give an enumerated type
without overloadding operators for the enumerated type...

Maybe we should have more than one kind of enumerations
or more precisely being able to give specifies some properties
for an enumeration. Enumeration could be used for contiguous
values, for flags, for constants,... and requirements are differents
for each uses and compatibility impose constraint on actual enums.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: danielgutson@hotmail.com (danielgutson@hotmail.com)
Date: Fri, 21 Feb 2003 21:09:33 +0000 (UTC)
Raw View
dsp@bdal.de (Daniel Spangenberg) wrote in message
news:<3E55FBBC.8260F496@bdal.de>...
>Hello Daniel Gutson!
>
>"danielgutson@hotmail.com" schrieb:
>
> > Hello.
> >
> >  I'd like to see your feedback about this proposal.
> >
>
>[snip]
>
>Your partioning of your posting is very fine! Maybe I should learn
from it
>(I
>made the experience, that my posting concerning fundamental flaws
have
not
>been answered or only very minorly)

Well, actually, I'm developing some theory that people only answers
when
they have a complain, so if they don't, ...   ;-)

I learnt the partition from a very good friend that some day told me
what
was going wrong :)  (thanks Howard! ;) )

(btw, I forgot to mention the 'Compatibility' section).
>
>   Yeah, I think also. The nice thing is, that the following code will
also
>(and needs to) work:
>
>    enum MyEnum { one, two };
>
>    MyEnum value = ...;  // Whatever
>
>    switch (value)
>    {
>    case 3: // Error!
>     ...
>     break;
>    case static_cast<MyEnum>(4): // OK, we know what we do!

Absolutely.

This would also be disabled (I mean, the general behavior) by

  switch ( (int)value)
   ...

>For short enum definitions this will be feasible, but not for longer
ones.
>For those cases it would be nice, if C/C++ would provide something
like
>PASCALS's enumeration ranges in case switches:

Maybe the '..' operator could be created for these situations:

  case enumValue1 .. enumValue2:

or

  case intValue1 .. intValue2:

without the need of a range.

The only drawback I'd mention is that this (the .. operator for case
labels) would be sensible to the enum value sequence definition.
If you have your code, including the enum, and someone comes and
changes the
enum order because thinks that this way is nicer, it will break the
code without notice...but, as always, we would arrive to the terrain
of
styles.

Anyway, I'm not so fan of using the fact that enums are implemented
thru integrals, and therefore using the    >    operator for them.
Opinions?

Thanks for your feedback!

Daniel.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: lvr@softsystem.co.uk ("Lawrence Rust")
Date: Sat, 22 Feb 2003 20:29:01 +0000 (UTC)
Raw View
<danielgutson@hotmail.com> wrote...
[snip]
> RULES.
>  Whenever a switch statement receives an enum type, the case labels
> should have the enum elements only.
> IF:
>   1) a case label is not, it means an error.
>   2) the case expressions don't cover all the enum members, and:
>     2.1) there's no DEFAULT label, a warning should be thrown.
>     2.2) there's a DEFAULT label, no warning is thrown, but (I think)
> a good practice would be avoiding DEFAULT labels for switch on enums
> and expliciting all the enum values. This would help mainteinance when
> the enum grows and we want that all the values are considered.

Several common compilers already issue warnings for such usage, given the
right compilation options.  For instance with gcc add -Wswitch.

-- Lawrence Rust, Software Systems, www.softsystem.co.uk
The problem with Windows XP: http://www.arachnoid.com/boycott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]