Topic: Extending enums (was Forward declaration of enum)


Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 24 Mar 2003 23:31:13 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote (abridged):
> > I don't have a reference, but I recall Stroustrup saying that he knew
> > well how to implement overloading by return type. It's easy for
> > compilers. He rejected it because he thought it was difficult for
> > humans.
>
> My recollection is different [...]
> Integer division should always be integer division, regardless of
> what's going to be done with the result.

Not really. We agree that the user's experience was the deciding factor,
rather than any perceived difficulty in implementation. You are being more
precise about what is likely to cause users problems.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: stephen.clamage@sun.com (Stephen Clamage)
Date: Wed, 19 Mar 2003 19:54:57 +0000 (UTC)
Raw View
On Mon, 17 Mar 2003 21:29:41 +0000 (UTC), allan_w@my-dejanews.com
(Allan W) wrote:

>brangdon@cix.co.uk (Dave Harris) wrote
>> hyrosen@mail.com (Hyman Rosen) wrote (abridged):
>> > Even when doing overloading by return types, overload resolution
>> > isn't that complicated to implement. And the problem was solved
>> > decdes ago.
>>
>> I don't have a reference, but I recall Stroustrup saying that he knew well
>> how to implement overloading by return type. It's easy for compilers. He
>> rejected it because he thought it was difficult for humans.
>
>My recollection is different (although I don't at this minute have
>access to anything at all to try to look it up). It seems to me that
>Stroustrup didn't want the division in this expression
>    int i = 10 / 3;
>to behave any differently than the division in this expression:
>    float x = 10 / 3;
>Integer division should always be integer division, regardless of
>what's going to be done with the result.
>
>At least, that's what I think he had in mind. Naturally, he would have
>explained it much better than I'm doing...

No, predefined operators on predefined types were never the issue. C++
deliberatly adopted the C rules, for compatbility. The only issue was
overloading of user-defined functions, and whether the return type
should enter into overloading rules.

The C++ overloading rules without overloading on return type are
extremely complicated, with many surprises for the unwary, and even
for the wary. Allowing overloading on return type would have added
more complexity without providing enough benefit (a judgement call) to
make it worthwhile.

That said, the use of user-defined conversion functions is in effect
overloading on return type, but in a restricted context.

---
[ 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: Wed, 12 Mar 2003 20:50:18 +0000 (UTC)
Raw View
    It's probably not worth the trouble, but maybe
it should be something like this:

 enum BasicColor: public int {Red, Green, Blue};
 enum AdvancedColor: public BasicColor {Teal, Puce, Lavender};

That lets you define the underlying type, which removes the
ambiguity about size.  The rule would be that you can't change
the underlying type when deriving a new enum type.

     Being able to define the underlying type is useful
when the machine representation is defined by something external,
like a network protocol definition.  Enums tend not to be used
in those situations because of the ambiguity about their size.

    John Nagle
    Animats

kgwzamboni-news@zambonistiscan.com wrote:
> On Sun, 9 Mar 2003 05:26:38 UTC, brangdon@cix.co.uk (Dave Harris) wrote:
>>kgwzamboni-news@zambonistiscan.com () wrote (abridged):
>>>How about also making them more like real types.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 12 Mar 2003 20:50:27 +0000 (UTC)
Raw View
dsp@bdal.de (Daniel Spangenberg) wrote (abridged):
> For the same reason, I nearly always encapsulate enumeration
> definitions into classes, like
>
> struct Color { enum Type { Red, Orange, Yellow }; };
>
> because I like the stronger enforcement of the complete name resolution
> of class namespaces.

I prefer the openness. This is partly because my local compiler supports
forward enum declarations, so I can write:

    namespace Colour { enum Type; }

If I tried that with a struct I'd come a cropper on the One Definition
Rule. (I use this language extension a lot - which is part of why I
advocate making it standard.)


> Why do you think, that Color::Type" is not a convenient identifier?

It's an invented name, a placeholder purely to satisfy the compiler. I'd
much rather be able to write:

    Colour c = Colour::Red;

Compare with:

    struct Colour {
        const Colour Red, Green, Blue;
    };

    Colour c = Colour::red;

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: richard@ex-parrot.com ("Richard Smith")
Date: Wed, 12 Mar 2003 20:51:57 +0000 (UTC)
Raw View
"Dave Harris" <brangdon@cix.co.uk> wrote:
> kgwzamboni-news@zambonistiscan.com () wrote (abridged):
> > Color(Orange) is similar to a copy constructor.
>
> It looks like one (or like a function call). In your suggestion it
> actually behaves differently - it tells us which version of Orange
> to use. It doesn't convert or copy an Orange because "Orange"
> without context doesn't mean anything.

It's actually very similar to the use of casts to determine which of a set
of overloaded functions to use:


  typedef void (*Colour)(int);
  void Orange(double);
  void Orange(int);

  Colour c = Colour(Orange);  // cast to type Colour disambiguates
                              // overloaded Orange.

So the language does already have one situation where the names are
determined from the context.  In fact, it has another -- the assignment of
overloaded function pointers:  the last line could equally well have been
written

  Colour c = Orange;  // assignment to variable of type Colour
                      // disambiguates overloaded Orange.

Given that compilers are able to disambiguate overloaded functions in this
way, I don't see any reason why they shouldn't be able to do the same with
enums.

--
Richard Smith



---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 12 Mar 2003 20:52:15 +0000 (UTC)
Raw View
comp.std.c++_2003-03-11@nmhq.net (Niklas Matthies) wrote (abridged):
> > If we have both kinds of overloading, we don't really know
> > where to start.
>
> Is this really conceptually different from types with (possibly
> multiple) implicit conversions used in overloaded function argument
> context?

It's conceptually different, but I agree not very practically different.

Another example is 0.

    int i = 0;
    double d = 0;
    int *p = 0;

One might imagine there are three different kinds of 0, with 3 different
types, but conceptually in C++ there is only one 0 and its type is int. In
both cases we start with an inner expression which is unambiguous, and
that expression does not change meaning as we add context.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 12 Mar 2003 20:52:27 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> [enums whose meaning depends on context]
> Ada has this, as part of its general ability to overload by return
> type. In fact, in Ada enumeration literals are considered to be
> parameterless functions which return their enumerator. This makes
> them work in the same way as other overloaded functions.

Agreed. If C++ ever gets overloading by return type, then this enum
proposal becomes a much smaller change.


> Even when doing overloading by return types, overload resolution
> isn't that complicated to implement. And the problem was solved
> decdes ago.

I don't have a reference, but I recall Stroustrup saying that he knew well
how to implement overloading by return type. It's easy for compilers. He
rejected it because he thought it was difficult for humans.

I've looked in D&E but couldn't find any discussion of the point.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: Thu, 13 Mar 2003 16:36:55 +0000 (UTC)
Raw View

Dave Harris schrieb:
[snip]

> I prefer the openness. This is partly because my local compiler supports
> forward enum declarations, so I can write:
>
>     namespace Colour { enum Type; }
>
> If I tried that with a struct I'd come a cropper on the One Definition
> Rule. (I use this language extension a lot - which is part of why I
> advocate making it standard.)

OK, under these circumstances the usage of namespaces would be preferable.
But to my mind, it would be more consistent, if the definition

enum Colour{ Red, Blue };

would be interpreted, such that naming their individual colours would enforce
us
to write Colour::Red  and Colour::Blue.

In case of unnamed enumerations this requirement has to fell, of course.

Although I think, that such a usage of enumeration members would be very
useful and type-save, I don't like its divergence from the C-meaning of
enums, so
instead of CHANGING the interpretation of

enum Colour{ Red, Blue };

I would propose the *addition* of a enumclass /classenum written as

enumclass Colour{Red, Blue};

where all members are must be *static* members, which might be either:

- static constants (which means the individual colours)
- typedefs
- maybe member functions (only those, which in normal classes would be static
functions)

What about this?

> > Why do you think, that Color::Type" is not a convenient identifier?
>
> It's an invented name, a placeholder purely to satisfy the compiler. I'd
> much rather be able to write:
>
>     Colour c = Colour::Red;
>
> Compare with:
>
>     struct Colour {
>         const Colour Red, Green, Blue;
>     };
>
>     Colour c = Colour::red;

But realize, that your given class example is no valid C++! You are using
class
members of the currently not defined class itself!

I think, a proposal, like the above mentioned type extension, would be a
cleaner solution to this problem.

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: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 14 Mar 2003 17:26:51 +0000 (UTC)
Raw View
dsp@bdal.de (Daniel Spangenberg) wrote (abridged):
> But to my mind, it would be more consistent, if the definition
>
> enum Colour{ Red, Blue };
>
> would be interpreted, such that naming their individual colours would
> enforce us to write Colour::Red  and Colour::Blue.

But this breaks too much existing code. My proposal allows this syntax but
doesn't require it.


> I would propose the *addition* of a enumclass /classenum written as
>
> enumclass Colour{Red, Blue};
>
> where all members are must be *static* members, which might be either:
>
> - static constants (which means the individual colours)
> - typedefs
> - maybe member functions (only those, which in normal classes would be
> static functions)
>
> What about this?

It seems very complicated and I don't understand the ramifications to say
whether the benefit is worth it.


> But realize, that your given class example is no valid C++! You
> are using class members of the currently not defined class itself!

So add some references. This:

    struct Colour {
        static const Colour &Red, &Green, &Blue;
    };

    Colour c = Colour::Red;

compiles at http://www.comeaucomputing.com/tryitout/


> I think, a proposal, like the above mentioned type extension, would be a
> cleaner solution to this problem.

I don't understand what you dislike about my proposal. In other words, to
allow:

   enum Colour { Red, Orange, Yellow };
   enum Fruit { Orange, Apple, Grapes }; // OK.

   Colour c1 = Red; // OK.
   Colour c2 = Orange; // Error - ambiguous.
   Colour c3 = Colour::Orange; // OK.

An enum creates a namespace and also adds an implicit using-declaration
for that namespace. This adds no new keywords, and as far as I know breaks
no existing code.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: Mon, 17 Mar 2003 16:56:59 +0000 (UTC)
Raw View

Dave Harris schrieb:
[snip]

> > What about this?
>
> It seems very complicated and I don't understand the ramifications to say
> whether the benefit is worth it.
>

Actually I don't see the complications (despite of course any complications
which are
always due to the introduction of new types).

> So add some references. This:
>
>     struct Colour {
>         static const Colour &Red, &Green, &Blue;
>     };
>
>     Colour c = Colour::Red;
>
> compiles at http://www.comeaucomputing.com/tryitout/
>

That is interesting, but I don't think that it does what an enum implies. Of
course you can
define references into a class which are references to instances to this
class, but they
don't provide integral values similar to enumerations. I mean, you cannot
write

int i = Colour::Red;

because their is no integral value represented by Colour::Red.
Maybe I don't understand your example. Please make that clearer to me!


> I don't understand what you dislike about my proposal. In other words, to
> allow:
>
>    enum Colour { Red, Orange, Yellow };
>    enum Fruit { Orange, Apple, Grapes }; // OK.
>
>    Colour c1 = Red; // OK.
>    Colour c2 = Orange; // Error - ambiguous.
>    Colour c3 = Colour::Orange; // OK.
>
> An enum creates a namespace and also adds an implicit using-declaration
> for that namespace. This adds no new keywords, and as far as I know breaks
> no existing code.

I didn't say and didn't mean, that I dislike your proposal. Actually it is
very fine and
it does not introduce so much changes, as those resulting from my *enumclass*
proposal.
I was just dreaming about the existence of such an extended enumeration class.

The advantages of such an extended type would be:
- stronger type savity (You are enforced to use Colour::Red)
- Natural inclusing of (static) functions into the same "enumclass" namespace

Good luck,

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: allan_w@my-dejanews.com (Allan W)
Date: Mon, 17 Mar 2003 21:29:41 +0000 (UTC)
Raw View
brangdon@cix.co.uk (Dave Harris) wrote
> hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> > Even when doing overloading by return types, overload resolution
> > isn't that complicated to implement. And the problem was solved
> > decdes ago.
>
> I don't have a reference, but I recall Stroustrup saying that he knew well
> how to implement overloading by return type. It's easy for compilers. He
> rejected it because he thought it was difficult for humans.

My recollection is different (although I don't at this minute have
access to anything at all to try to look it up). It seems to me that
Stroustrup didn't want the division in this expression
    int i = 10 / 3;
to behave any differently than the division in this expression:
    float x = 10 / 3;
Integer division should always be integer division, regardless of
what's going to be done with the result.

At least, that's what I think he had in mind. Naturally, he would have
explained it much better than I'm doing...

---
[ 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, 7 Mar 2003 20:17:49 +0000 (UTC)
Raw View
In article <PNE21WKuwwiy-pn2-dMoOpvv8cPkQ@zamboni.stiscan.com>,
kgwzamboni-news@zambonistiscan.com writes
>On Tue, 4 Mar 2003 16:45:34 UTC, nagle@animats.com (John Nagle) wrote:
>How about also making them more like real types.
>
>enum Color( Red, Orange, Yellow );
>enum Fruit( Orange, Apple, Grapes );
>
>Except when assigning them directly to ints, the compiler is capable
>of determining which Orange it is.
>For that case allow the cast like Color(Orange).
>
>Then dumb things like "Color x = Grapes;" would be flaged.

However we hit the same problem that we have with forward declaration,
that of different enums having different sizes in C++.

Yes I know derived class objects are usually larger than their base
class objects, but in the case of enums we have the problem of
enumeration constants. Suppose in the above example that Colour
instances have a size of 1 and Fruit ones have a size of 2. What should
be the size of Red before the definition of Fruit, and after it?


--
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: kgwzamboni-news@zambonistiscan.com
Date: Fri, 7 Mar 2003 21:58:49 +0000 (UTC)
Raw View
On Fri, 7 Mar 2003 20:17:49 UTC, francis.glassborow@ntlworld.com (Francis Glassborow) wrote:

> In article <PNE21WKuwwiy-pn2-dMoOpvv8cPkQ@zamboni.stiscan.com>,
> kgwzamboni-news@zambonistiscan.com writes
> >On Tue, 4 Mar 2003 16:45:34 UTC, nagle@animats.com (John Nagle) wrote:
> >How about also making them more like real types.
> >
> >enum Color( Red, Orange, Yellow );
> >enum Fruit( Orange, Apple, Grapes );
> >
> >Except when assigning them directly to ints, the compiler is capable
> >of determining which Orange it is.
> >For that case allow the cast like Color(Orange).
> >
> >Then dumb things like "Color x = Grapes;" would be flaged.
>
> However we hit the same problem that we have with forward declaration,
> that of different enums having different sizes in C++.
>
> Yes I know derived class objects are usually larger than their base
> class objects, but in the case of enums we have the problem of
> enumeration constants. Suppose in the above example that Colour
> instances have a size of 1 and Fruit ones have a size of 2. What should
> be the size of Red before the definition of Fruit, and after it?
>
>
Red does not have a size.
Color and Fruit do in this example.
Maybe you want
long enum and
short enum  etc. for forwards.
--
Remove zamboni to reply.
All the above is hearsay and the not quaranteed.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Sun, 9 Mar 2003 05:26:38 +0000 (UTC)
Raw View
kgwzamboni-news@zambonistiscan.com () wrote (abridged):
> How about also making them more like real types.
>
> enum Color( Red, Orange, Yellow );
> enum Fruit( Orange, Apple, Grapes );
>
> Except when assigning them directly to ints, the compiler is capable
> of determining which Orange it is.

It is a bit dangerous to have names whose meaning depends on context.


> For that case allow the cast like Color(Orange).

It's not really a cast; more of a name resolution. I think it is a shame
enums do not have associated namespaces, so that we could write:

   enum Color { Red, Orange, Yellow };
   enum Fruit { Orange, Apple, Grapes };

   Colour c = Colour::Orange;

Currently the second line is ambiguous even if Orange is not used
subsequently, and the Colour::Orange syntax is not permitted. As a
workaround I usually put my own namespace, like:

   namespace Color { enum Type { Red, Orange, Yellow }; }
   namespace Fruit { enum Type { Orange, Apple, Grapes } };

   Colour::Type c = Colour::Orange;

which works, but it is clumsy (eg there is no good name for the thing I
have called "Type").

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: Mon, 10 Mar 2003 14:32:52 +0000 (UTC)
Raw View
Dave Harris schrieb:

> It's not really a cast; more of a name resolution. I think it is a shame
> enums do not have associated namespaces, so that we could write:
>
>    enum Color { Red, Orange, Yellow };
>    enum Fruit { Orange, Apple, Grapes };
>
>    Colour c = Colour::Orange;
>
> Currently the second line is ambiguous even if Orange is not used
> subsequently, and the Colour::Orange syntax is not permitted. As a
> workaround I usually put my own namespace, like:
>
>    namespace Color { enum Type { Red, Orange, Yellow }; }
>    namespace Fruit { enum Type { Orange, Apple, Grapes } };
>
>    Colour::Type c = Colour::Orange;
>
> which works, but it is clumsy (eg there is no good name for the thing I
> have called "Type").
>

For the same reason, I nearly always encapsulate enumeration definitions into
classes,
like

struct Color { enum Type { Red, Orange, Yellow }; };

because I like the stronger enforcement of the complete name resolution of
class namespaces.

Why do you think, that Color::Type" is not a convenient identifier? Actually
I use the same
identifier and I think it is both short and self-explaining.

Greetings from Bremen/Germany

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: kgwzamboni-news@zambonistiscan.com
Date: Mon, 10 Mar 2003 18:21:57 +0000 (UTC)
Raw View
On Sun, 9 Mar 2003 05:26:38 UTC, brangdon@cix.co.uk (Dave Harris) wrote:

> kgwzamboni-news@zambonistiscan.com () wrote (abridged):
> > How about also making them more like real types.
> >
> > enum Color( Red, Orange, Yellow );
> > enum Fruit( Orange, Apple, Grapes );
> >
> > Except when assigning them directly to ints, the compiler is capable
> > of determining which Orange it is.
>
> It is a bit dangerous to have names whose meaning depends on context.

How is it any more dangerous than overloaded function declarations?

>
>
> > For that case allow the cast like Color(Orange).
>
> It's not really a cast; more of a name resolution. I think it is a shame
> enums do not have associated namespaces, so that we could write:
>
>    enum Color { Red, Orange, Yellow };
>    enum Fruit { Orange, Apple, Grapes };
>
>    Colour c = Colour::Orange;

Same thing, different notation.
Color(Orange) is similar to a copy constructor.

>
> Currently the second line is ambiguous even if Orange is not used
> subsequently, and the Colour::Orange syntax is not permitted. As a
> workaround I usually put my own namespace, like:
>
>    namespace Color { enum Type { Red, Orange, Yellow }; }
>    namespace Fruit { enum Type { Orange, Apple, Grapes } };
>
>    Colour::Type c = Colour::Orange;
>
> which works, but it is clumsy (eg there is no good name for the thing I
> have called "Type").
>

But I would expect even in this case to be able to write:
Colour::Type c = Orange;

And have it resolved by lookup rules.

Extending it again:

namespace Color{ enum Color{ Red, Orange };}

Then I would want what I had before.

Color c = Orange;

And have it resolved by lookup.

C, C++ and Java enums have always been bordering on poor design.
I think the extension I purposed should not invalidate any already existing programs
except to given warnings in some poorly designed ones.

The original proposal of this thread on "enum inheritance" should be included with it.



>   Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
>       brangdon@cix.co.uk      |   And close your eyes with holy dread,
>                               |  For he on honey dew hath fed
>  http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."
>
> ---
> [ 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                       ]
>


--
Remove zamboni to reply.
All the above is hearsay and the not guaranteed.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 10 Mar 2003 21:44:20 +0000 (UTC)
Raw View
kgwzamboni-news@zambonistiscan.com () wrote (abridged):
> > It is a bit dangerous to have names whose meaning depends
> > on context.
>
> How is it any more dangerous than overloaded function
> declarations?

The real problem comes when we have both. With overloaded functions,
we can figure out the meaning by starting in the middle and working
out. Thus:
    func( a, b );

we first figure out the type of a and b, and then figure out which
func() is the best match. If we have as enum name which depends on
context, then:
    func( orange );

we go in the opposite direction: figure out which func() to use and
then figure out which version of orange it wants. If we have both
kinds of overloading, we don't really know where to start.

What you are suggesting here is a pretty major change, because of
this.


> >    Colour c = Colour::Orange;
>
> Same thing, different notation.

Yes. I thought it was close enough to achieve what you want, while
being a better fit to the existing language.


> Color(Orange) is similar to a copy constructor.

It looks like one (or like a function call). In your suggestion it
actually behaves differently - it tells us which version of Orange
to use. It doesn't convert or copy an Orange because "Orange"
without context doesn't mean anything.

Enums already support this syntax with its copy constructor meaning.
Eg:

    OsFileMode { read, execute, write };

    OsFileMode m = OsMode( 1 );

Supposing we had the new overloading, we could write:

    OsFileMode { read, execute, write );
    UserFileMode { read, write, append );

    OsMode m1 = OsMode( UserFileMode::write );

    OsMode m2 = OsMode( UserFileMode( write ) );

M1 uses my syntax; I think it makes it relatively clear that there
are two different things happening, a name resolution and a cast.
And the name resolution happens at compile-time and is safe where-as the
cast happens at run-time and is potentially dangerous.

M2 uses your syntax. Although the middle part looks like a dangerous
cast, it isn't. Or to put it another way, the outer part looks like
a safe name resolution, but isn't. Another example:

     OsMode m3 = OsMode( read_write );

Is this a safe name resolution, or a dangerous cast?

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: Hyman Rosen <hyrosen@mail.com>
Date: Tue, 11 Mar 2003 11:14:04 CST
Raw View
Dave Harris wrote:
> If we have both kinds of overloading, we don't really know where to start.
> What you are suggesting here is a pretty major change, because of this.

Ada has this, as part of its general ability to overload by return type.
In fact, in Ada enumeration literals are considered to be parameterless
functions which return their enumerator. This makes them work in the same
way as other overloaded functions. Even when doing overloading by return
types, overload resolution isn't that complicated to implement. And the
problem was solved decdes ago.

---
[ 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: Niklas Matthies <comp.std.c++_2003-03-11@nmhq.net>
Date: Tue, 11 Mar 2003 11:14:12 CST
Raw View
On 2003-03-10 21:44, Dave Harris <brangdon@cix.co.uk> wrote:
> kgwzamboni-news@zambonistiscan.com () wrote (abridged):
>> > It is a bit dangerous to have names whose meaning depends
>> > on context.
>>
>> How is it any more dangerous than overloaded function
>> declarations?
>
> The real problem comes when we have both. With overloaded functions,
> we can figure out the meaning by starting in the middle and working
> out. Thus:
>     func( a, b );
>
> we first figure out the type of a and b, and then figure out which
> func() is the best match. If we have as enum name which depends on
> context, then:
>     func( orange );
>
> we go in the opposite direction: figure out which func() to use and
> then figure out which version of orange it wants. If we have both
> kinds of overloading, we don't really know where to start.
>
> What you are suggesting here is a pretty major change, because of
> this.

Is this really conceptually different from types with (possibly
multiple) implicit conversions used in overloaded function argument
context?

Say:

   namespace fruit { enum type { orange /* ... */ }; }
   namespace color { enum type { orange /* ... */ }; }

   struct generic_orange
   {
      operator fruit::type () const { return fruit::orange; }
      operator color::type () const { return color::orange; }
   };

   generic_orange const orange = generic_orange();

   void g(fruit::type f);

   void h(fruit::type f);
   void h(color::type c);

   void f()
   {
      g(orange);  // okay
      h(orange);  // ambiguous
   }

-- Niklas Matthies

---
[ 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: Tue, 11 Mar 2003 18:56:56 +0000 (UTC)
Raw View
> kgwzamboni-news@zambonistiscan.com writes
> >On Tue, 4 Mar 2003 16:45:34 UTC, nagle@animats.com (John Nagle) wrote:

No, John Nagle did not write the next few lines, kgwzamboni-news did.
(KGW?) Giving a source not followed by >quote'd lines, implies that
the text which immediately follows was written by someone else. A false
implication, in this case.

kgw, please try to be careful with your attributions -- I don't know
if Mr. Nagle would be upset quoting ideas to him, but I would!

> >How about also making them more like real types.
> >enum Color( Red, Orange, Yellow );
> >enum Fruit( Orange, Apple, Grapes );
> >
> >Except when assigning them directly to ints, the compiler is capable
> >of determining which Orange it is.
> >For that case allow the cast like Color(Orange).
> >
> >Then dumb things like "Color x = Grapes;" would be flaged.
>
francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> However we hit the same problem that we have with forward declaration,
> that of different enums having different sizes in C++.
>
> Yes I know derived class objects are usually larger than their base
> class objects, but in the case of enums we have the problem of
> enumeration constants. Suppose in the above example that Colour
> instances have a size of 1 and Fruit ones have a size of 2. What should
> be the size of Red before the definition of Fruit, and after it?

Since Fruit is not derived from Color, I would say that there should be
no effect.

Recasting your question to a more appropriate heirarchy:

  enum lowcolors {
      red,
      green,
      blue,
      // lots more here... but not so much as to force lowcolors
      // to be larger than the default size for enums
      max
   };
   enum highcolors {
      pink = lowcolors::maxvalue,
      magenta,
      cyan,
      // Lots more here... enough to force
      // sizeof(highcolors)>sizeof(lowcolors)
      maxvalue
    };
Now you're asking if the existance of enum highcolors ought to have any
effect on enum lowcolors. Of course, if anyone says that it should, they're
throwing away the entire concept of seperate compilation...

I suppose a simpler way to handle the difference is to add some code
(syntax left for another day) that tells the compiler that it's okay
to implicitly convert a lowcolor into a highcolor.

I agree with Lawrence Rust that the idea of using inheritance seems
obvious... and I agree with Hyman Rosen that when examined more deeply,
it's actually backwards from normal inheritance relationships.

In any case, we cannot use a highcolor where a lowcolor is expected,
but perhaps we could arrange things so that a lowcolor could be used
wherever a highcolor is expected.

    highcolor h1 = pink; // Of course
    highcolor h2 = blue; // Implicit conversion
    lowcolor  L1 = blue; // Of course
    lowcolor  L2 = pink; // ?Always undefined?

We might allow that last statement when sizeof(highcolor) happens to
equal sizeof(lowcolor). Or, we might make it always illegal.

---
[ 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: usenet@phatbasset.com ("Hillel Y. Sims")
Date: Wed, 12 Mar 2003 05:26:36 +0000 (UTC)
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:HFeba.21313$gi1.5997@nwrdny02.gnilink.net...
>  Even when doing overloading by return
> types, overload resolution isn't that complicated to
implement. And the
> problem was solved decdes ago.
>

Would it call 'void foo()' below?

void foo();
float foo();

int main()
{
   foo();  // ?
}

thanks,
hys
--
(c) 2003 Hillel Y. Sims
hsims AT factset.com

---
[ 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: kgwzamboni-news@zambonistiscan.com
Date: Wed, 12 Mar 2003 18:46:17 +0000 (UTC)
Raw View
On Mon, 10 Mar 2003 21:44:20 UTC, brangdon@cix.co.uk (Dave Harris) wrote:


> we first figure out the type of a and b, and then figure out which
> func() is the best match. If we have as enum name which depends on
> context, then:
>     func( orange );
>
> we go in the opposite direction: figure out which func() to use and
> then figure out which version of orange it wants. If we have both
> kinds of overloading, we don't really know where to start.
>

When the compiler looks up Orange and it sees more than one
it considers all of them and looks up "func".
If it finds more than one match, it is ambiguous.
Otherwise it knows which enum was meant.
Not any worse than template lookup.

--
Remove zamboni to reply.
All the above is hearsay and the not quaranteed.

---
[ 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: acappellaguy@hotmail.com (A Cappella Guy)
Date: Wed, 5 Mar 2003 17:47:58 +0000 (UTC)
Raw View
In article <mKY8a.1209$U24.78230781@newssvr21.news.prodigy.com>, John
Nagle <nagle@animats.com> wrote:

>    More usefully, some way to define a new enum type which
> references another enum type and is guaranteed not to have
> clashing values would be useful.  Something like
>
>  enum lowcolors { red, green, blue };
> ....
>  enum highcolors{ pink=lastof(lowcolors), magenta, cyan };
>
> It's common to see a new set of constants started from the
> last value of another set in some previously defined file.
> This breaks when someone adds a new constant in the first file.

I routinely define my enums like so:

enum lowcolors { red = 0, green, blue, numLowColors };

Helps with using the values as table offsets and matching the table
size, but in your example would also make it easy to specify:

enum highcolors { pink = numLowColors, magenta, cyan,
numLowAndHighColors };

 -- A Cappella Guy

---
[ 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: Thu, 6 Mar 2003 00:34:26 +0000 (UTC)
Raw View
"John Nagle" wrote...
>    More usefully, some way to define a new enum type which
> references another enum type and is guaranteed not to have
> clashing values would be useful.  Something like
>
> enum lowcolors { red, green, blue };
> ....
> enum highcolors{ pink=lastof(lowcolors), magenta, cyan };
>
> It's common to see a new set of constants started from the
> last value of another set in some previously defined file.
> This breaks when someone adds a new constant in the first file.
>
>     Probably not worth the trouble, though.

Wouldn't it be more logical to use inheritance?  Then one could write:

enum highcolors: public lowcolors { pink, magenta, cyan };

Just a thought.

-- 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: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 6 Mar 2003 18:33:49 +0000 (UTC)
Raw View
Lawrence Rust wrote:
> Wouldn't it be more logical to use inheritance?  Then one could write:
> enum highcolors: public lowcolors { pink, magenta, cyan };

This is backwards from normal inheritance - you can use the "base"
enum wherever the "derived" enum is required, but not vice versa.

---
[ 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: Thu, 6 Mar 2003 21:17:16 +0000 (UTC)
Raw View
"Hyman Rosen" wrote...
> Lawrence Rust wrote:
> > Wouldn't it be more logical to use inheritance?  Then one could write:
> > enum highcolors: public lowcolors { pink, magenta, cyan };
>
> This is backwards from normal inheritance - you can use the "base"
> enum wherever the "derived" enum is required, but not vice versa.

True, it's more in keeping with the common and biological usage of the term
i.e. successive generations inherit common characteristics with the
possibility of adding or even losing a few.

It just struck me that this might form the basis for mathematical groups and
fields if you added operators.

-- 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: kgwzamboni-news@zambonistiscan.com
Date: Thu, 6 Mar 2003 21:55:10 +0000 (UTC)
Raw View
On Tue, 4 Mar 2003 16:45:34 UTC, nagle@animats.com (John Nagle) wrote:
How about also making them more like real types.

enum Color( Red, Orange, Yellow );
enum Fruit( Orange, Apple, Grapes );

Except when assigning them directly to ints, the compiler is capable
of determining which Orange it is.
For that case allow the cast like Color(Orange).

Then dumb things like "Color x = Grapes;" would be flaged.
--
Remove zamboni to reply.
All the above is hearsay and the not quaranteed.

---
[ 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: Tue, 4 Mar 2003 16:45:34 +0000 (UTC)
Raw View
   More usefully, some way to define a new enum type which
references another enum type and is guaranteed not to have
clashing values would be useful.  Something like

 enum lowcolors { red, green, blue };
....
 enum highcolors{ pink=lastof(lowcolors), magenta, cyan };

It's common to see a new set of constants started from the
last value of another set in some previously defined file.
This breaks when someone adds a new constant in the first file.

    Probably not worth the trouble, though.

   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                       ]