Topic: inherited enums.


Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 29 May 1994 15:22:20 GMT
Raw View
In article <Cq3017.6z5@world.std.com> miket@world.std.com (Michael Trachtman) writes:

Subclassing, inheritance ....
>
>The language "C++" does not specify anything like that. Rather,
>what you are proposing is a methodology for using the features
>that C++ offers.

 The terminological distinction I make is that between
subtyping and inheritance. Inheritance can be used to do
subtyping. It can also be used to do composition and many
other things.

>pointers to the base class. (And even in this case  think
>that the methodology that a subclass should be a sub-type is only
>a guideline rather than a strict requirement.)

 To make dynamic linkage of derived objects work,
subclassing is a strict requirement. Such dynamic linkage
ensures the whole of the derived class is invisible and
only the abstraction can be seen. Working in such a
constrained environment really makes you think your designs
through carefully -- and pays big dividends in the end.

>
>However, I don't agree with the methodology in the general case.
>As I wrote earlier, other uses of inheritance are useful.

 So are techniques OTHER than inheritance.
Such as functional decomposition, which is much better understood.

>All that the language says is that the derived class has all
>the features of the parents PLUS some additional structure.
>
>I look forward to reading opposing (or concurring) views.

 What does "structure" mean?
Structure is what a block of marble has after Michaelangelo
has been at it: structure is imparted to unrestricted
media by imposing restrictions: the restrictions ARE the
structure.

 So "ADDING structure" IS adding extra restrictions,
which reduces the set of values the entity can have.
MORE structure == LESS cases.

 <grin>


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Fri, 20 May 1994 07:56:35 +0000
Raw View
In article <Cq3017.6z5@world.std.com>
           miket@world.std.com "Michael Trachtman" writes:

>Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
>: This a classic mistake with inheritance: the subclass actually specifies
>: a subset of the objects that are compatible with the superclass - sub and
>: super apply in this case to both the class and the candidate objects they
>: describe. So the inheritor always constrains the parent, ie. it defines
>: a subset of objects, even tho its interface may be wider (if you are
>: interested references I will mail them to you).
>
>The language "C++" does not specify anything like that. Rather,
>what you are proposing is a methodology for using the features
>that C++ offers. You are also proposing a methodology on how
>NOT to use the features that C++ offers. I agree with the
>general idea of the methodology at least when you use subclassing
>together with virtual functions and containers that hold generic
>pointers to the base class. (And even in this case  think
>that the methodology that a subclass should be a sub-type is only
>a guideline rather than a strict requirement.)
>
>However, I don't agree with the methodology in the general case.
>As I wrote earlier, other uses of inheritance are useful.
>All that the language says is that the derived class has all
>the features of the parents PLUS some additional structure.
>
>I look forward to reading opposing (or concurring) views.
>
>Michael  T.

You are correct in stating that C++ does not use these terms. I couched
my reply in general OO terms, but I think you will find that the C++
type system is geared towards inheritance as type extension. You may
choose to use it another way, but type conformance is still defined
by inheritance. If B inherits publicly from A, then a B may be used
where an A is expected even if B is not a design subtype of A - the language
will not stop you from using inheritance another way, but it won't help
you.

Protected and private inheritance follow the same pattern, but restrict
client use to specific classes - almost as good as inheritance for
reuse only.
--
Kevlin Henney

 repeat 3 echo there\'s no place like ~




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Mon, 23 May 1994 11:50:57 GMT
Raw View
In article <Cq10It.FIL@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
>: In article <CpM60n.Ip0@world.std.com>
>:            miket@world.std.com "Michael Trachtman" writes:
>
>: >I have had to "inherit" enum values.
>: >I was wondering whether it would be reasonable to add
>: >the ability to inherit from an enum to C++.
>[stuff deleted]
>
>: The desire is understandable, but it is not actually meaningful if you
>: think of what a base class actually specifies in terms of sets: a
>: derived class actually describes _fewer_ candidate objects than the
>: parent. To fit this model and the principle of substituteability, a
>: derived enum class would actually have fewer enums than its parent!
>
> I am unconvinced. Sure, in "theory", subclassing should be an IS-A
>relationship. However, I am unconvinced that that is the only
>correct use of subclassing.

 Please. Subclassing MEANS is-a relationship. It is true
that inheritance can be used for other than subclassing.
In particular, it can, and is, used for composition.
And MOST of the time, it is used for BOTH simultaneously.
(restrict the base value set, then add more attributes)

>In many cases, you inherit interfaces,
>and then add to that interface.
>In fact, from a purely mathematical standpoint, inheriting is
>additive, i.e. the inheritor is always a super-set of the class
>being inherited from, since inheritance means: I will have all
>   of the data and methods from the class I inherited from PLUS
>    anything additional  that I add in this new class.

 But proper subclassing is NOT additive. Thats
why so much C++ code doesnt work properly. A whole bunch
of programmers do NOT know how to do subclassing and make it work!

 The set of states of a subtype is LESS than that of the
supertype. Dont take it from me: take it from the International
Standards Organisation Draft International Standard
for Language Independent Datatypes: (DIS 11404)

 "Subtype: A subtype is a datatype derived from an
existing datatype, designated the base type, by restricting
the value space to a subset of that of the base datatype whilst
maintaining all characterizing operations."

 Now there is something important to note here.
The "value space" is the PUBLICALLY accessible set of states
of an object. And how is that set of states usually accessed?

 Using methods! But doesnt that mean you have
to implement the same methods in a derived class as a base one,
to act to exhibit less states? Yes! Only, by default
using inheritance you get the same method, but you can override
a virtual function (specialise it) to make it more
efficient.

 How can it be more efficient? Because it is only
working with a subset of the values. For example, consider:

 class Matrix { // 100x100 matrix of floats ..
  virtual void transpose(); // swap m[i][j] with m[j][i]
 };
 class SymmetricMatrix : public virtual Matrix {..
  virtual void transpose(){} // FAST!!
 };

Can I add a 'colour' to me SymmetricMatrix?

Look, I cant STOP you. But if you do it isnt a pure subtype.
I mean, is a coloured matrix a matrix?

Well.. no. Its not. Only if you forget the colour!
(Heard of 'slicing'? Well, thats what it does. Aka
the 'forgetful functor' in Category theory)

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: Gary Powell <gary_powell@aldus.com>
Date: 17 May 1994 17:11:25 GMT
Raw View
Re: inherited enums.
In article <2raj79$l27@explorer.clark.net> Taylor Hutt, thutt@clark.net
writes:
>So, if in one source file you have:
>
>   enum vegetation { grass, grain, tree };
>
>and in another, you have
>
>   enum fruits : vegetation { apple, orange }
>
>and finally in another
>
>   enum moregrain : vegetation { barley, corn, wheat }
>
>
>You have a problem because an enumeration is simply an integer!
>
>So, vegetation::grass is assigned a value of 0 at compile time.
>    fruits::apple is given a value of 3 at compile time
>    moregrain::barley is ALSO given a value of 3 at compile time
>                         ^^^^ without all sorts of added complexity
>
>Now, since extension of a type allows assignment to its base (in pointer
>form, usually), please tell me how you intend allow assignment of an
>extended enum to a base enum, in a type/value safe manner?
>
>Consider the following:
>
>  vegetation v;
>  fruit f;
>  moregrain m;
>
>  v = f;             // legal? (if not, what is the real use?)
>  f = v;             // legal?  (certainly should be)
>
>  f = fruit::apple;  // better be legal
>  v = f;             // still legal?
>  m = v;             // whoa, wait a minute, this won't work....


I don't see how you can let a vegetation get a value from a fruit which
is outside the range of the vegetation. You should throw an exception or
issue a warning
at compile time at least.  Unfortunatly the compiler may not know the
value, ie.

in file1.cpp
CheckVitamins(vegetation v)
{
   do something with v
}

in file2.cpp
fruit GetUserSelectedFruit()
{
   Querry the user for the fruit of the day....
}
main()
{
    fruit f = GetUserSelectedFruit();

    CheckVitamins(f);  // This can't be legal as the compiler has no way
           // of knowing whether the fruit is also within the range of
the
           // vegetation.
 }

Therefore the extension as proposed is not complete. Besides as shown in
several previous postings there are acceptable work a rounds that are
type safe, which do allow concatination of enum values.

I do however prefer to design a series of classes which don't rely on
extending the enums. However I've seen worse stuff using #defines for
all the error message numbers.

IMHO using enums or defines is infinitly easier to read and maintain than
using a raw number.

if (errorCondition)
 {
 cout << errTableLookUp(OutOfMyMind);
 }

 vs

if (errorCondition)
 {
 cout << errTableLookUp(123);
 }

 However when I am tracking down error messages I do have to look in
 several places for the message number, and the text, and where is it
 used. That's the price you pay to internationalize your software.

 -Gary-
Gary Powell  | Internet: gary.powell@aldus.com
411 1st Ave S.  | Tel:   (206) 622-5500
Seattle, WA 98104 |




Author: daniels@biles.com (Brad Daniels)
Date: Tue, 17 May 1994 16:21:10 GMT
Raw View
In article <2raj79$l27@explorer.clark.net>,
Taylor Hutt <thutt@clark.net> wrote:
[much discussion ellided]
>You are making a great leap here by saying that extending enums is a good
>idea.  It has been tried, and it does not work well.  The compiler does
>not have a way to know (without considerable added complexity (which is
>unwarrranted, given the specious gains for extending enumerations)) which
>extended types are which.  Why?  Because an enumeration is a compile time
>constant (plain and simple, that is indisputable (page 523 of C++ Prog.
>Lang, 2nd edition and page 508 as well)).
>
>So, if in one source file you have:
>
>   enum vegetation { grass, grain, tree };
>
>and in another, you have
>
>   enum fruits : vegetation { apple, orange }
>
>and finally in another
>
>   enum moregrain : vegetation { barley, corn, wheat }
>
>
>You have a problem because an enumeration is simply an integer!
>
>So, vegetation::grass is assigned a value of 0 at compile time.
>    fruits::apple is given a value of 3 at compile time
>    moregrain::barley is ALSO given a value of 3 at compile time
>                         ^^^^ without all sorts of added complexity
>
>Now, since extension of a type allows assignment to its base (in pointer
>form, usually), please tell me how you intend allow assignment of an
>extended enum to a base enum, in a type/value safe manner?
>
>Consider the following:
>
>  vegetation v;
>  fruit f;
>  moregrain m;
>
>  v = f;             // legal? (if not, what is the real use?)
>  f = v;             // legal?  (certainly should be)
>
>  f = fruit::apple;  // better be legal
>  v = f;             // still legal?
>  m = v;             // whoa, wait a minute, this won't work....
>
>
>It gets worse still if you want to pass parameters, and allow extended
>enums to be passed!

I had been interpreting the desired semantics as having extended enums be
considered a superset of another enum, not a subclass.  In other words, your
"v = f" assignment above wouldn't be legal without an intervening explicit
conversion to integer.  In the comment, you ask what the use would be were
"v = f" not legal.  The use is that I can define an extended enumeration
which includes the values of another enumeration.  I can then define members
which use my extended enumeration and pass values of the subset enumeration
on to base class members which know how to handle such values.  To extend
your example (though this particular extension is a bit strained):

class mulcher {
    // ...
  public:
    // ...

    virtual void mulch(vegetation v) { /* ... */ }
};

class sortingMulcher : public mulcher {
    // ...
  public:
    // ...

    virtual void mulch(vegetation v) { mulcher::mulch(v); }
    virtual void mulch(fruit f)
    {
 switch (f) {
     case apple:
      // ...
      break;
     case orange:
      // ...
      break;
     default:
      // Must be generic vegetation.  We know the conversion is
      // safe because we've handled all fruits not in enum
  // vegetation.
      mulch(vegetation((int)f));
 }
    }
}

- Brad
--------------------------------------------------------------------------
+ Brad Daniels                  | I won't argue epistemology with you    +
+ Biles and Associates          | until you can prove unequivocally that +
+ These are my views, not B&A's | you are arguing epistemology with me.  +
--------------------------------------------------------------------------




Author: miket@world.std.com (Michael Trachtman)
Date: Thu, 19 May 1994 01:37:40 GMT
Raw View
Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
: In article <CpM60n.Ip0@world.std.com>
:            miket@world.std.com "Michael Trachtman" writes:

: >I have had to "inherit" enum values.
: >I was wondering whether it would be reasonable to add
: >the ability to inherit from an enum to C++.
[stuff deleted]

: The desire is understandable, but it is not actually meaningful if you
: think of what a base class actually specifies in terms of sets: a
: derived class actually describes _fewer_ candidate objects than the
: parent. To fit this model and the principle of substituteability, a
: derived enum class would actually have fewer enums than its parent!

 I am unconvinced. Sure, in "theory", subclassing should be an IS-A
relationship. However, I am unconvinced that that is the only
correct use of subclassing. In many cases, you inherit interfaces,
and then add to that interface.
In fact, from a purely mathematical standpoint, inheriting is
additive, i.e. the inheritor is always a super-set of the class
being inherited from, since inheritance means: I will have all
   of the data and methods from the class I inherited from PLUS
    anything additional  that I add in this new class.


Michael T.




Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Thu, 19 May 1994 07:55:42 +0000
Raw View
In article <Cq10It.FIL@world.std.com>
           miket@world.std.com "Michael Trachtman" writes:

>Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
>: In article <CpM60n.Ip0@world.std.com>
>:            miket@world.std.com "Michael Trachtman" writes:
>
>: >I have had to "inherit" enum values.
>: >I was wondering whether it would be reasonable to add
>: >the ability to inherit from an enum to C++.
>[stuff deleted]
>
>: The desire is understandable, but it is not actually meaningful if you
>: think of what a base class actually specifies in terms of sets: a
>: derived class actually describes _fewer_ candidate objects than the
>: parent. To fit this model and the principle of substituteability, a
>: derived enum class would actually have fewer enums than its parent!
>
> I am unconvinced. Sure, in "theory", subclassing should be an IS-A
>relationship. However, I am unconvinced that that is the only
>correct use of subclassing. In many cases, you inherit interfaces,
>and then add to that interface.
>In fact, from a purely mathematical standpoint, inheriting is
>additive, i.e. the inheritor is always a super-set of the class
>being inherited from, since inheritance means: I will have all
>   of the data and methods from the class I inherited from PLUS
>    anything additional  that I add in this new class.
>
>Michael T.

This a classic mistake with inheritance: the subclass actually specifies
a subset of the objects that are compatible with the superclass - sub and
super apply in this case to both the class and the candidate objects they
describe. So the inheritor always constrains the parent, ie. it defines
a subset of objects, even tho its interface may be wider (if you are
interested references I will mail them to you). More accurately, I
should be describing this in terms of type rather than class, but there
is no way of genuinely separating them in C++, altho in this respect
it's better than most.
--
Kevlin Henney

 repeat 3 echo there\'s no place like ~




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 18 May 1994 13:49:28 GMT
Raw View
In article <2r7n78$cbi@explorer.clark.net> thutt@clark.net (Taylor Hutt) writes:
>In article <CpsKxD.DLJ@ucc.su.oz.au>,
>John Max Skaller <maxtal@physics.su.OZ.AU> wrote:
>>In article <rfgCpsA0y.K4M@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>>>In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>>
>> The following is an adaption of a technique used by Borland.
>>
>> struct BASIC_COLOURS {
>>  enum tag {first = 0, red=first, blue, green, last = green} val;
>> };
>> struct SPECIAL_COLOURS  {
>>  enum tag {dummy=BASIC_COLOURS::first,
>>   burgundy = BASIC_COLOURS::last+1,
>>   navy, silicone_blue, last = silicone_blue} val;
>>  SPECIAL_COLOURS(BASIC_COLOURS::tag v)
>>  : val( static_cast<SPECIAL_COLOURS>(v.val) ) {}
>> };
>>Yes, the idiom is messy!
>
>That is not an idiom, it is idiotic.

 I cant disagree with that. :-)

>The purpose of an enum is to
>read-ify a source program; this rubbish only obfuscates the intent of the
>programmer in a shell that must be deciphered before the idea is
>extracted, and as such it ruins the purpose of an enum.

 No argument with you there.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 18 May 1994 17:02:13 GMT
Raw View
In article <2raj79$l27@explorer.clark.net> thutt@clark.net (Taylor Hutt) writes:
>
>So, if in one source file you have:
>
>   enum vegetation { grass, grain, tree };
>
>and in another, you have
>
>   enum fruits : vegetation { apple, orange }
>
>and finally in another
>
>   enum moregrain : vegetation { barley, corn, wheat }
>
>You have a problem because an enumeration is simply an integer!
>
>So, vegetation::grass is assigned a value of 0 at compile time.
>    fruits::apple is given a value of 3 at compile time
>    moregrain::barley is ALSO given a value of 3 at compile time
>                         ^^^^ without all sorts of added complexity
>
>Now, since extension of a type allows assignment to its base (in pointer
>form, usually), please tell me how you intend allow assignment of an
>extended enum to a base enum, in a type/value safe manner?

 The point is that most programmers not only misunderstand
inheritance, they get it _completely_ backwards. There is NOTHING
WRONG with:

   enum vegetation { grass, grain, tree };
   enum fruits : vegetation { apple, orange };
   enum moregrain : vegetation { barley, corn, wheat };

The problem is that fruits is not a subtype of vegetation.
Its the other way around: vegatation is obviously a subtype of
fruits: its a subset! The inheritance diagram is:

 fruits  moregrain
  \ /
  vegetation

The fact that the : notation is opposite to normal use and intuition here
is not surprising if you have the wrong idea about inheritance
in the first place. Too many people simply dont understand that
the set of states of a subtype (as viewed from the supertype),
must be a subset of the states of the supertype, and that
the subset IS what is called the invariant of the subtype.

 It is exactly the restriction of a subtype to a subset
that allows more efficient representations and faster algorithms
to be written, that is specialisations.

 An excellent example is symmetric matrices -- a subtype
of general ones.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: miket@world.std.com (Michael Trachtman)
Date: Fri, 20 May 1994 03:22:18 GMT
Raw View
Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
: In article <Cq10It.FIL@world.std.com>
:            miket@world.std.com "Michael Trachtman" writes:

: >Kevlin Henney (kevlin@wslint.demon.co.uk) wrote:
: >: In article <CpM60n.Ip0@world.std.com>
: >:            miket@world.std.com "Michael Trachtman" writes:
: >
: >: >I have had to "inherit" enum values.
: >: >I was wondering whether it would be reasonable to add
: >: >the ability to inherit from an enum to C++.
: >[stuff deleted]
: >
: >: The desire is understandable, but it is not actually meaningful if you
: >: think of what a base class actually specifies in terms of sets: a
: >: derived class actually describes _fewer_ candidate objects than the
: >: parent. To fit this model and the principle of substituteability, a
: >: derived enum class would actually have fewer enums than its parent!
: >
: > I am unconvinced. Sure, in "theory", subclassing should be an IS-A
: >relationship. However, I am unconvinced that that is the only
: >correct use of subclassing. In many cases, you inherit interfaces,
: >and then add to that interface.
: >In fact, from a purely mathematical standpoint, inheriting is
: >additive, i.e. the inheritor is always a super-set of the class
: >being inherited from, since inheritance means: I will have all
: >   of the data and methods from the class I inherited from PLUS
: >    anything additional  that I add in this new class.
: >
: >Michael T.

: This a classic mistake with inheritance: the subclass actually specifies
: a subset of the objects that are compatible with the superclass - sub and
: super apply in this case to both the class and the candidate objects they
: describe. So the inheritor always constrains the parent, ie. it defines
: a subset of objects, even tho its interface may be wider (if you are
: interested references I will mail them to you).

The language "C++" does not specify anything like that. Rather,
what you are proposing is a methodology for using the features
that C++ offers. You are also proposing a methodology on how
NOT to use the features that C++ offers. I agree with the
general idea of the methodology at least when you use subclassing
together with virtual functions and containers that hold generic
pointers to the base class. (And even in this case  think
that the methodology that a subclass should be a sub-type is only
a guideline rather than a strict requirement.)

However, I don't agree with the methodology in the general case.
As I wrote earlier, other uses of inheritance are useful.
All that the language says is that the derived class has all
the features of the parents PLUS some additional structure.

I look forward to reading opposing (or concurring) views.


Michael  T.




Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Tue, 17 May 1994 12:34:11 +0000
Raw View
In article <769163811snz@wslint.demon.co.uk>
           Kevlin@wslint.demon.co.uk "Kevlin Henney" writes:

>and type incorrect by inspection alone. It is, however, meaningful to
>restrict enum constants and preserve correct typing, eg. (no particular
>implementation language)
>
>        Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet };
>        Primary : Colours { Red, Green, Blue };

I realised after posting that although I say 'no particular implementation
language', it could be written in C++ish with the addition of only one
word:

 enum Rainbow { Red, Orange, Yellow, Green, Blue, Indigo, Violet };
 enum Primary : Rainbow { Red, Green, Blue };

The base name is also slightly more accurate now - constraining the world
to only 7 colours is a little overzealous :-)
--
Kevlin Henney

 In DOS, I know not why I am so sad,
 It wearies me; you say it wearies you;
 But how I caught it, found it, or came by it,
 What stuff 'tis made of, whereof it is born,
 I am to learn;

  The Merchant of Venice (I.i)




Author: thutt@clark.net (Taylor Hutt)
Date: 16 May 1994 07:59:36 -0400
Raw View
In article <CpsKxD.DLJ@ucc.su.oz.au>,
John Max Skaller <maxtal@physics.su.OZ.AU> wrote:
>In article <rfgCpsA0y.K4M@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>>In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>
> The following is an adaption of a technique used by Borland.
>
> struct BASIC_COLOURS {
>  enum tag {first = 0, red=first, blue, green, last = green} val;
> };
> struct SPECIAL_COLOURS  {
>  enum tag {dummy=BASIC_COLOURS::first,
>   burgundy = BASIC_COLOURS::last+1,
>   navy, silicone_blue, last = silicone_blue} val;
>  SPECIAL_COLOURS(BASIC_COLOURS::tag v)
>  : val( static_cast<SPECIAL_COLOURS>(v.val) ) {}
> };
>
>Explanation: the 'dummy' is required to ensure that a SPECIAL_COLOUR
>includes all the values of a BASIC_COLOUR.
>
>A BASIC_COLOUR can be used 'as a' SPECIAL_COLOUR due to the
>implicit conversion implied by the constructor. Please note
>that BASIC_COLOUR is a subtype of SPECIAL_COLOUR and not
>the other way around.
>
>Yes, the idiom is messy!

That is not an idiom, it is idiotic.  The purpose of an enum is to
read-ify a source program; this rubbish only obfuscates the intent of the
programmer in a shell that must be deciphered before the idea is
extracted, and as such it ruins the purpose of an enum.  The fact that
people accept this kind of garbage workaround to a problem that does not
exist at all is indicative of the complexity inherent in the language.

Research has proven that extending enums introduces all sorts of
problems: assignements, type checking and additional compiler
complexity.  Further, other research has proven that enums are not
necessary.

Think before you leap.  That first step might be a big one.




Author: miket@world.std.com (Michael Trachtman)
Date: Mon, 16 May 1994 12:42:09 GMT
Raw View
Taylor Hutt (thutt@clark.net) wrote:
: In article <CpsKxD.DLJ@ucc.su.oz.au>,
: John Max Skaller <maxtal@physics.su.OZ.AU> wrote:
: >In article <rfgCpsA0y.K4M@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
: >>In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
: >
: > The following is an adaption of a technique used by Borland.
: >
: > struct BASIC_COLOURS {
: >  enum tag {first = 0, red=first, blue, green, last = green} val;
: > };
: > [stuff deleted...]

: That is not an idiom, it is idiotic.  The purpose of an enum is to
: read-ify a source program; this rubbish only obfuscates the intent of the
: programmer in a shell that must be deciphered before the idea is
: extracted, and as such it ruins the purpose of an enum.  The fact that
: people accept this kind of garbage workaround to a problem that does not
: exist at all is indicative of the complexity inherent in the language.

: Research has proven that extending enums introduces all sorts of
: problems: assignements, type checking and additional compiler
: complexity.  Further, other research has proven that enums are not
: necessary.

I don't understand.
First you say that:
   "The purpose of an enum is to read-ify a source program"
Later you said:
   "Further, other research has proven that enums are not necessary."
Which is it ?

Also, could you please give references to "other research" ?
Is this other research conclusive ? Or is it an opinion ?

Finally, if extending enums is a good idea then the fact that there
are problems should not stand in the way. Problems are there to
keep analysts and other problem solvers employed.


Michael T.




Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Tue, 17 May 1994 08:36:51 +0000
Raw View
In article <2r7n78$cbi@explorer.clark.net> thutt@clark.net "Taylor Hutt" writes:
[workaround deleted]
>>Yes, the idiom is messy!
>
>That is not an idiom, it is idiotic.  The purpose of an enum is to
>read-ify a source program; this rubbish only obfuscates the intent of the
>programmer in a shell that must be deciphered before the idea is
>extracted, and as such it ruins the purpose of an enum.  The fact that
>people accept this kind of garbage workaround to a problem that does not
>exist at all is indicative of the complexity inherent in the language.

Did we get out of bed the wrong side this morning?

>Research has proven that extending enums introduces all sorts of
>problems: assignements, type checking and additional compiler

Research is not necessary. I indicated in an earlier posting in this
thread that the notion of extending enums by subtyping is meaningless
and type incorrect by inspection alone. It is, however, meaningful to
restrict enum constants and preserve correct typing, eg. (no particular
implementation language)

 Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet };
 Primary : Colours { Red, Green, Blue };

>complexity.  Further, other research has proven that enums are not
>necessary.

Research has also shown that the only a GOTO and a single branch IF
are required for control flow. Stop writing content-free sentences.

>Think before you leap.  That first step might be a big one.

See my previous sentence wrt your last sentence.
--
Kevlin Henney

 In DOS, I know not why I am so sad,
 It wearies me; you say it wearies you;
 But how I caught it, found it, or came by it,
 What stuff 'tis made of, whereof it is born,
 I am to learn;

  The Merchant of Venice (I.i)




Author: thutt@clark.net (Taylor Hutt)
Date: 17 May 1994 10:09:45 -0400
Raw View
In article <CpwBAA.CFn@world.std.com>,
Michael Trachtman <miket@world.std.com> wrote:
>Taylor Hutt (thutt@clark.net) wrote:
>: In article <CpsKxD.DLJ@ucc.su.oz.au>,
>: John Max Skaller <maxtal@physics.su.OZ.AU> wrote:
>: >In article <rfgCpsA0y.K4M@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>: >>In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>: >
>: > The following is an adaption of a technique used by Borland.
>: >
>: > struct BASIC_COLOURS {
>: >  enum tag {first = 0, red=first, blue, green, last = green} val;
>: > };
>: > [stuff deleted...]
>
>: That is not an idiom, it is idiotic.  The purpose of an enum is to
>: read-ify a source program; this rubbish only obfuscates the intent of the
>: programmer in a shell that must be deciphered before the idea is
>: extracted, and as such it ruins the purpose of an enum.  The fact that
>: people accept this kind of garbage workaround to a problem that does not
>: exist at all is indicative of the complexity inherent in the language.
>
>: Research has proven that extending enums introduces all sorts of
>: problems: assignements, type checking and additional compiler
>: complexity.  Further, other research has proven that enums are not
>: necessary.
>
>I don't understand.
>First you say that:
>   "The purpose of an enum is to read-ify a source program"
>Later you said:
>   "Further, other research has proven that enums are not necessary."
>Which is it ?

One thing has nothing to do with the next.  Let me see if I can put it in
terms that you might understand:

A: The purpose of smoking marijuana is to get you high.
B: Marijuana is not needed.

The original intent of enumerations in many langauges was to make a
program more readable by removing all the literals that often littered a
program.  However, over time, everything under the sun was enumerated,
and it turned out that enumerations added to the verbosity of the
programs without making it more readable (You had to keep looking for the
types and enumeration members).  As for the research itself, check out
Project Oberon (Addison Wesley) and _From Modula to Oberon_
(neptune.inf.ethz.ch, /Oberon/Docu)

>Finally, if extending enums is a good idea then the fact that there
>are problems should not stand in the way. Problems are there to
>keep analysts and other problem solvers employed.

You are making a great leap here by saying that extending enums is a good
idea.  It has been tried, and it does not work well.  The compiler does
not have a way to know (without considerable added complexity (which is
unwarrranted, given the specious gains for extending enumerations)) which
extended types are which.  Why?  Because an enumeration is a compile time
constant (plain and simple, that is indisputable (page 523 of C++ Prog.
Lang, 2nd edition and page 508 as well)).

So, if in one source file you have:

   enum vegetation { grass, grain, tree };

and in another, you have

   enum fruits : vegetation { apple, orange }

and finally in another

   enum moregrain : vegetation { barley, corn, wheat }


You have a problem because an enumeration is simply an integer!

So, vegetation::grass is assigned a value of 0 at compile time.
    fruits::apple is given a value of 3 at compile time
    moregrain::barley is ALSO given a value of 3 at compile time
                         ^^^^ without all sorts of added complexity

Now, since extension of a type allows assignment to its base (in pointer
form, usually), please tell me how you intend allow assignment of an
extended enum to a base enum, in a type/value safe manner?

Consider the following:

  vegetation v;
  fruit f;
  moregrain m;

  v = f;             // legal? (if not, what is the real use?)
  f = v;             // legal?  (certainly should be)

  f = fruit::apple;  // better be legal
  v = f;             // still legal?
  m = v;             // whoa, wait a minute, this won't work....


It gets worse still if you want to pass parameters, and allow extended
enums to be passed!

Please think about all the ramifications before you try to push a change.


Taylor Hutt
All typoes are intentional




Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Thu, 12 May 1994 14:01:28 +0000
Raw View
In article <CpM60n.Ip0@world.std.com>
           miket@world.std.com "Michael Trachtman" writes:

>I have had to "inherit" enum values.
>I was wondering whether it would be reasonable to add
>the ability to inherit from an enum to C++.
>
>An example is:
>
>enum BASIC_COLOR {
>   red,
>   green,
>   blue
>};
>
>enum SPECIAL_COLORS : BASIC_COLOR {
>    navy,
>    burgundy,
>    silicon_blue
>};
>
>The meaning of this should be obvious: SPECIAL_COLORS has all the
>values that BASIC_COLOR has plus some additional ones.

The desire is understandable, but it is not actually meaningful if you
think of what a base class actually specifies in terms of sets: a
derived class actually describes _fewer_ candidate objects than the
parent. To fit this model and the principle of substituteability, a
derived enum class would actually have fewer enums than its parent!

>In the application that I have, I actually need multiple inheritance.
>In particular, there is a collection of modules. Each module declares
>some error_values that it can return. We then want to make a master
>list of errors.
[...]
>Michael Trachtman

I think you will have to take the class approach. Single extension
would break the type system, but multiple would leave very little
standing. Consider a higher level symbolic approach to handling errors.
--
Kevlin Henney

 In DOS, I know not why I am so sad,
 It wearies me; you say it wearies you;
 But how I caught it, found it, or came by it,
 What stuff 'tis made of, whereof it is born,
 I am to learn;

  The Merchant of Venice (I.i)




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sat, 14 May 1994 08:24:34 GMT
Raw View
In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>I have had to "inherit" enum values.
>I was wondering whether it would be reasonable to add
>the ability to inherit from an enum to C++.
>
>An example is:
>
>enum BASIC_COLOR {
>   red,
>   green,
>   blue
>};
>
>enum SPECIAL_COLORS : BASIC_COLOR {
>    navy,
>    burgundy,
>    silicon_blue
>};
>
>The meaning of this should be obvious: SPECIAL_COLORS has all the
>values that BASIC_COLOR has plus some additional ones.

I've considered the same idea myself.

I happen to think that it's a swell idea, but I'm afraid that its far far
too late in the standardization process to be adding this now.

--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 14 May 1994 12:20:00 GMT
Raw View
In article <rfgCpsA0y.K4M@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>In article <CpM60n.Ip0@world.std.com> miket@world.std.com (Michael Trachtman) writes:
>>I have had to "inherit" enum values.
>>I was wondering whether it would be reasonable to add
>>the ability to inherit from an enum to C++.
>>
>>An example is:
>>
>>enum BASIC_COLOR {
>>   red,
>>   green,
>>   blue
>>};
>>
>>enum SPECIAL_COLORS : BASIC_COLOR {
>>    navy,
>>    burgundy,
>>    silicon_blue
>>};
>>
>>The meaning of this should be obvious: SPECIAL_COLORS has all the
>>values that BASIC_COLOR has plus some additional ones.
>
>I've considered the same idea myself.
>
>I happen to think that it's a swell idea, but I'm afraid that its far far
>too late in the standardization process to be adding this now.

 The following is an adaption of a technique used by Borland.

 struct BASIC_COLOURS {
  enum tag {first = 0, red=first, blue, green, last = green} val;
 };
 struct SPECIAL_COLOURS  {
  enum tag {dummy=BASIC_COLOURS::first,
   burgundy = BASIC_COLOURS::last+1,
   navy, silicone_blue, last = silicone_blue} val;
  SPECIAL_COLOURS(BASIC_COLOURS::tag v)
  : val( static_cast<SPECIAL_COLOURS>(v.val) ) {}
 };

Explanation: the 'dummy' is required to ensure that a SPECIAL_COLOUR
includes all the values of a BASIC_COLOUR.

A BASIC_COLOUR can be used 'as a' SPECIAL_COLOUR due to the
implicit conversion implied by the constructor. Please note
that BASIC_COLOUR is a subtype of SPECIAL_COLOUR and not
the other way around.

Yes, the idiom is messy!

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: miket@world.std.com (Michael Trachtman)
Date: Sat, 14 May 1994 18:49:40 GMT
Raw View
Taylor Hutt (thutt@clark.net) wrote:
: In article <CpM60n.Ip0@world.std.com>,
: Michael Trachtman <miket@world.std.com> wrote:
: >I have had to "inherit" enum values.
: >I was wondering whether it would be reasonable to add
: >the ability to inherit from an enum to C++.
[stuff deleted ]

: And how do you propose to make sure that each time you inherit from
: SPECIAL_COLORS that it not conflict with any other value already used in
: another inheritance from another source file?

I do not follow. What does it matter if it does conflict.
e.g. enum COLOR { RED = 1, GREEN, BLUE};
enum COLOR2: virtual public COLOR { BROWN, YELLOW };
enum COLOR3: virtual public COLOR { WHITE, GREY };
enum COLOR4: virtual public COLOR, COLOR2, COLOR3 { PURPLE, PINK };

I do not see a problem that WHITE probably has different values
in COLOR3 and COLOR4. If somewhere you have;

COLOR3 c3 = WHITE; // The bit pattern is 0x04.
COLOR4 c4 = WHITE; // The bit pattern is 0x06.
COLOR4 c4a;

if (c3 == c4)    // This is true even though the actual bit
                 // values are different.
     c4a = PINK; // The bit value is 0x09.
else
     c4a = GREEN;

: // in another header file from your SPECIAL colors (completely disjoint)

: enum NewSpecial_Colors : BASIC_COLOR {
:     fucia,
:     shitbrundlebrown,
:     mauve
: };

: How does the compiler know that BASIC_COLOR is extended in another
: direction also?

It doesn't have to until you use both in the same expression.
At that time, it knows both.

: This concept has already been tried in another object-oriented language
: and rejected because it does not work well at all.




Author: miket@world.std.com (Michael Trachtman)
Date: Wed, 11 May 1994 01:12:22 GMT
Raw View
I have had to "inherit" enum values.
I was wondering whether it would be reasonable to add
the ability to inherit from an enum to C++.

An example is:

enum BASIC_COLOR {
   red,
   green,
   blue
};

enum SPECIAL_COLORS : BASIC_COLOR {
    navy,
    burgundy,
    silicon_blue
};

The meaning of this should be obvious: SPECIAL_COLORS has all the
values that BASIC_COLOR has plus some additional ones.

In the application that I have, I actually need multiple inheritance.
In particular, there is a collection of modules. Each module declares
some error_values that it can return. We then want to make a master
list of errors.

Something like the following:

/* In file module_a.h */
enum MODULE_A_ERRORS {
     ERR_A_BASE = 1000,
     ERR_A_XYZ,
     ERR_A_ZZZ
} ;

 ....
/* In file module_l.h */
enum MODULE_L_ERRORS {
     ERR_L_BASE = 1200,
     ERR_L_SOME_ERROR_CODE,
     ERR_L_ZZZ1
} ;

...

/* And finally somewhere else */
#include "module_a.h"
#include ...
#include "module_l.h"
#include ...

enum MODULE_ALL_ERRORS
  : MODULE_A_ERRORS, ..., MODULE_L_ERRORS, ...
{
};


Has this feature already been proposed ?
It seems to be in line with the general direction that C++ is
noting that enum's are types just like classes are,
and should have many of the same features.

Of course, these ideas could easily be extended to allow
you to give "methods" to an enum. However, I am not asking about
that in this posting. (Though I probably should.)


Michael Trachtman




Author: thutt@clark.net (Taylor Hutt)
Date: 11 May 1994 07:30:41 -0400
Raw View
In article <CpM60n.Ip0@world.std.com>,
Michael Trachtman <miket@world.std.com> wrote:
>I have had to "inherit" enum values.
>I was wondering whether it would be reasonable to add
>the ability to inherit from an enum to C++.
>
>An example is:
>
>enum BASIC_COLOR {
>   red,
>   green,
>   blue
>};
>
>enum SPECIAL_COLORS : BASIC_COLOR {
>    navy,
>    burgundy,
>    silicon_blue
>};
>
>The meaning of this should be obvious: SPECIAL_COLORS has all the
>values that BASIC_COLOR has plus some additional ones.

And how do you propose to make sure that each time you inherit from
SPECIAL_COLORS that it not conflict with any other value already used in
another inheritance from another source file?

// in another header file from your SPECIAL colors (completely disjoint)

enum NewSpecial_Colors : BASIC_COLOR {
    fucia,
    shitbrundlebrown,
    mauve
};

How does the compiler know that BASIC_COLOR is extended in another
direction also?

This concept has already been tried in another object-oriented language
and rejected because it does not work well at all.




Author: Gary Powell <gary_powell@aldus.com>
Date: 11 May 1994 16:26:37 GMT
Raw View
Re: inherited enums.

One other possible soln. for your error numbering problem is this. It
relys on you keeping the enum numbering scheme straight since the union
won't tell you which class the enum came from.

The other disadvantage is that the constructor set for the enclosing
class gets large as it needs to take in any of the union of error types.
Also if the enum's are different sizes part of the data may be garbage.
So you will want to have a max value for each type so that they are all
the same size. (I recall a proposal to add type specifiers to enums but I
haven't seen a compiler which allows it.)

Its advantage is that it doesn't add a new feature to C++.

#include <iostream.h>

class basic_colors {
public:
 ~basic_colors() {};
 enum color { red, green, blue };
 basic_colors(color item) : fitem(item) {};
 color mfGetColor() { return fitem; };
private:
 color fitem;
};

class extended_colors {
public:
 ~extended_colors() {};
 enum ecolor { fucia, orange, purple };
 extended_colors( basic_colors::color item ) {fitem.colorItem = item;};
 extended_colors( ecolor item ) { fitem.ecolorItem = item; };
 ecolor mfGetColor() { return fitem.ecolorItem; };
private:
 union {
  basic_colors::color colorItem;
  ecolor ecolorItem;
  } fitem;
};


void main ()
{
 extended_colors foo(basic_colors::red);

 switch (foo.mfGetColor() )
 {
 case basic_colors::red:
  cout << "Red";
  break;
 case extended_colors::orange:
  cout << "orange";
  break;
 }
 cout << endl;
}
Gary Powell  | Internet: gary.powell@aldus.com
411 1st Ave S.  | Tel:   (206) 622-5500
Seattle, WA 98104 |