Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c++ > #224 > unrolled thread

New strongly type enum proposal featuring inherited enums

Started byPhil Bouchard <philippe@fornux.com>
First post2011-08-16 21:28 -0600
Last post2011-08-24 17:40 -0700
Articles 20 on this page of 28 — 18 participants

Back to article view | Back to comp.std.c++


Contents

  New strongly type enum proposal featuring inherited enums Phil Bouchard <philippe@fornux.com> - 2011-08-16 21:28 -0600
    Re: New strongly type enum proposal featuring inherited enums Daniel Krügler <daniel.kruegler@googlemail.com> - 2011-08-18 07:54 -0600
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 14:06 -0700
        Re: New strongly type enum proposal featuring inherited enums Daniel Krügler<daniel.kruegler@googlemail.com> - 2011-08-24 17:39 -0700
          Re: New strongly type enum proposal featuring inherited enums Bart van Ingen Schenau<bart@ingen.ddns.info> - 2011-08-25 20:51 -0600
            Re: New strongly type enum proposal featuring inherited enums =3D?ISO-8859-15?Q?Daniel_Kr=3DFCgler?=3D <daniel.kruegler@googlemail.= com> - 2011-09-07 11:08 -0700
              Re: New strongly type enum proposal featuring inherited enums Miles Bader <miles@gnu.org> - 2011-09-08 14:46 -0700
                Re: New strongly type enum... why not use "using"? "peter miller"<fuchsia.groan@virgin.net> - 2011-09-12 11:18 -0700
                  Re: New strongly type enum... why not use "using"? Miles Bader<miles@gnu.org> - 2011-09-13 09:29 -0700
                    Re: New strongly type enum... why not use "using"? "peter miller"<fuchsia.groan@virgin.net> - 2011-09-15 14:13 -0700
    Re: New strongly type enum proposal featuring inherited enums Pete Becker <pete@versatilecoding.com> - 2011-08-18 07:51 -0600
      Re: New strongly type enum proposal featuring inherited enums Victor Bazarov<v.bazarov@comcast.invalid> - 2011-08-24 14:06 -0700
      Re: New strongly type enum proposal featuring inherited enums Paavo Helde<myfirstname@osa.pri.ee> - 2011-08-24 14:06 -0700
      Re: New strongly type enum proposal featuring inherited enums Francis Glassborow<francis.glassborow@btinternet.com> - 2011-08-24 14:52 -0700
        Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 17:39 -0700
    Re: New strongly type enum proposal featuring inherited enums Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2011-08-18 07:53 -0600
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 14:52 -0700
    Re: New strongly type enum proposal featuring inherited enums Marcel Müller <news.5.maazl@spamgourmet.com> - 2011-08-18 07:52 -0600
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-23 18:20 -0700
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard <philippe@fornux.com> - 2011-08-24 14:52 -0700
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard <philippe@fornux.com> - 2011-08-24 14:52 -0700
    Re: New strongly type enum proposal featuring inherited enums Francis Glassborow<francis.glassborow@btinternet.com> - 2011-08-24 14:06 -0700
    Re: New strongly type enum proposal featuring inherited enums "Bo Persson"<bop@gmb.dk> - 2011-08-24 14:06 -0700
    Re: New strongly type enum proposal featuring inherited enums red floyd<no.spam.here@its.invalid> - 2011-08-24 14:06 -0700
    Re: New strongly type enum proposal featuring inherited enums Seungbeom Kim<musiphil@bawi.org> - 2011-08-24 14:06 -0700
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 17:39 -0700
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 17:40 -0700
      Re: New strongly type enum proposal featuring inherited enums Phil Bouchard<philippe@fornux.com> - 2011-08-24 17:40 -0700

Page 1 of 2  [1] 2  Next page →


#224 — New strongly type enum proposal featuring inherited enums

FromPhil Bouchard <philippe@fornux.com>
Date2011-08-16 21:28 -0600
SubjectNew strongly type enum proposal featuring inherited enums
Message-ID<4e49ea26$2@news.x-privat.org>
Hi,

Is it too late to change the strongly type enum?  I have a proposal
that is much cleaner than what is on its way.

Right now we have:
enum class Val: unsigned long { E1, E2, E3, E4 };

Comments:
1) This design is bad because the ':' sign is reserved for inheritance.

2) Inheriting from another enum would be quite useful.  For example:
enum class Widget {button, combobox, listview};
enum class SuperWidget : Widget {iconview}

This way iconview would be equal to 3, not 0.

3) Redefining the underlying type could be easily done with:
enum class Val { unsigned long E1, E2, E3, E4 };

This is much more neat and is similar to a declaration of multiple instances:
const unsigned long E1, E2, E3, E4;


Thanks,
-Phil


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [next] | [standalone]


#226

FromDaniel Krügler <daniel.kruegler@googlemail.com>
Date2011-08-18 07:54 -0600
Message-ID<j2inpn$aa2$1@dont-email.me>
In reply to#224
On 2011-08-17 05:28, Phil Bouchard wrote:
>
> Hi,
>
> Is it too late to change the strongly type enum?

Yes, the ISO standard C++11 is accepted.

> I have a proposal
> that is much cleaner than what is on its way.
>
> Right now we have:
> enum class Val: unsigned long { E1, E2, E3, E4 };
>
> Comments:
> 1) This design is bad because the ':' sign is reserved for inheritance.

I disagree. First, ':' is only "reserved" for inheritance for class
types, second, even, if we look at it similar to class types I don't
consider the current state as incorrect, because we can (conceptually)
consider an enum to "derive from" an underlying type.

> 2) Inheriting from another enum would be quite useful. For example:
> enum class Widget {button, combobox, listview};
> enum class SuperWidget : Widget {iconview}

The current state would not disallow such an extension in the future,
so what is the problem?

> This way iconview would be equal to 3, not 0.

Maybe, that would depend on an actual proposal that describes the
semantics in this way.

> 3) Redefining the underlying type could be easily done with:
> enum class Val { unsigned long E1, E2, E3, E4 };
>
> This is much more neat and is similar to a declaration of multiple
> instances:
> const unsigned long E1, E2, E3, E4;

I don't consider this alternative as superior as the current state. To
me it looks, as if Ei (i=1-4) are data members of Val. It would imply
to me that I could write

enum class Val { unsigned long E1; unsigned long E2; unsigned long E3,
unsigned long E4; };

Does that mean that we could also use different underlying types for
individual enumerator values?

HTH & Greetings from Bremen,

- Daniel Krügler


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#237

FromPhil Bouchard<philippe@fornux.com>
Date2011-08-24 14:06 -0700
Message-ID<4e4d462b@news.x-privat.org>
In reply to#226
On 8/18/2011 9:54 AM, Daniel Krügler wrote:
>
>>  2) Inheriting from another enum would be quite useful. For example:
>>  enum class Widget {button, combobox, listview};
>>  enum class SuperWidget : Widget {iconview}
>
>  The current state would not disallow such an extension in the future,
>  so what is the problem?

I don't think it'll be a good idea to make the two coexist together:
enum class SuperWidget : Widget {iconview} // derived
enum class SuperWidget : unsigned int {iconview} // subtyping

>>  3) Redefining the underlying type could be easily done with:
>>  enum class Val { unsigned long E1, E2, E3, E4 };
>>
>>  This is much more neat and is similar to a declaration of multiple
>>  instances:
>>  const unsigned long E1, E2, E3, E4;
>
>  I don't consider this alternative as superior as the current state. To
>  me it looks, as if Ei (i=1-4) are data members of Val. It would imply
>  to me that I could write
>
>  enum class Val { unsigned long E1; unsigned long E2; unsigned long E3,
>  unsigned long E4; };
>
>  Does that mean that we could also use different underlying types for
>  individual enumerator values?

Only one declaration would be allowed.  A semicolon could even be accepted:
enum class Val { unsigned long E1, E2, E3, E4; };


Regards,
-Phil


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#251

FromDaniel Krügler<daniel.kruegler@googlemail.com>
Date2011-08-24 17:39 -0700
Message-ID<j33rkg$qrl$1@dont-email.me>
In reply to#237
Am 24.08.2011 23:06, schrieb Phil Bouchard:
>  On 8/18/2011 9:54 AM, Daniel Krügler wrote:
>>
>>>  2) Inheriting from another enum would be quite useful. For example:
>>>  enum class Widget {button, combobox, listview};
>>>  enum class SuperWidget : Widget {iconview}
>>
>>  The current state would not disallow such an extension in the future,
>>  so what is the problem?
>
>  I don't think it'll be a good idea to make the two coexist together:
>  enum class SuperWidget : Widget {iconview} // derived
>  enum class SuperWidget : unsigned int {iconview} // subtyping

I'm missing the rationale for your dislike. Widget is still a type that
has an integral type as underlying type, so what is the drastic
difference, if you extend scoped enums to allow for extending another
enum? We have no enumeration values in integral types, so we have we
don't have an observable difference. If you want to define that
SuperWidget contains the enumeration values of Widget, this is simply a
definition problem.

>>>  3) Redefining the underlying type could be easily done with:
>>>  enum class Val { unsigned long E1, E2, E3, E4 };
>>>
>>>  This is much more neat and is similar to a declaration of multiple
>>>  instances:
>>>  const unsigned long E1, E2, E3, E4;
>>
>>  I don't consider this alternative as superior as the current state. To
>>  me it looks, as if Ei (i=1-4) are data members of Val. It would imply
>>  to me that I could write
>>
>>  enum class Val { unsigned long E1; unsigned long E2; unsigned long E3,
>>  unsigned long E4; };
>>
>>  Does that mean that we could also use different underlying types for
>>  individual enumerator values?
>
>  Only one declaration would be allowed. A semicolon could even be accepted:
>  enum class Val { unsigned long E1, E2, E3, E4; };

You are starting now a design which comes way too late, C++11 has left
the house. We can proceed discussing this here, but I must say, I'm
failing to see the advantages. The current specification is now part of
an International Standard and I could not find any arguments in this
thread that demonstrate the defect of the current specification.

Greetings from Bremen,

- Daniel Krügler



-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#257

FromBart van Ingen Schenau<bart@ingen.ddns.info>
Date2011-08-25 20:51 -0600
Message-ID<j352gi$7n1$1@localhost.localdomain>
In reply to#251
Daniel Krügler<daniel.kruegler@googlemail.com>  Wrote:

>  Am 24.08.2011 23:06, schrieb Phil Bouchard:
>  >   On 8/18/2011 9:54 AM, Daniel Krügler wrote:
>  >>
>  >>>   2) Inheriting from another enum would be quite useful. For
>  example:
>  >>>   enum class Widget {button, combobox, listview};
>  >>>   enum class SuperWidget : Widget {iconview}
>  >>
>  >>   The current state would not disallow such an extension in the
>  future,
>  >>   so what is the problem?
>  >
>  >   I don't think it'll be a good idea to make the two coexist
>  together:
>  >   enum class SuperWidget : Widget {iconview} // derived
>  >   enum class SuperWidget : unsigned int {iconview} // subtyping
>
>  I'm missing the rationale for your dislike. Widget is still a type that
>  has an integral type as underlying type, so what is the drastic
>  difference, if you extend scoped enums to allow for extending
>  another enum? We have no enumeration values in integral types, so
>  we have we don't have an observable difference. If you want to
>  define that SuperWidget contains the enumeration values of
>  Widget, this is simply a definition problem.

The dislike probably comes from how an enum is typically viewed.
To my knowledge, an enum is typically viewed as an integer with a limited
set of possible values (that some/most of those values also have a symbolic
name is incidental). A scoped enum gives you the added value of being able
to specify the underlying storage.

With this view the interpretation of the declarations would be:
  enum class Widget : unsigned int { list_view, box, button }; /* RESTRICT a
storage cell of size unsigned int to store only the specified values */
  enum class SuperWidget : Widget { iconview }; /* EXTEND? the allowed values
to include iconview */

OTOH, you seem to view a (scoped) enum as its base-type with some of the
values given a symbolic name:

  enum class Widget : unsigned int { list_view, box, button }; /* Can store
all values of an unsigned int, with three of them given a specific,
symbolic, name */
  enum class SuperWidget : Widget { iconview }; /* Extend the list of
symbolic names to include iconview */

>
>  Greetings from Bremen,
>
>  - Daniel Krügler

Bart v Ingen Schenau


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#279

From=3D?ISO-8859-15?Q?Daniel_Kr=3DFCgler?=3D <daniel.kruegler@googlemail.= com>
Date2011-09-07 11:08 -0700
Message-ID<j38ert$b18$1@dont-email.me>
In reply to#257
Am 26.08.2011 04:51, schrieb Bart van Ingen Schenau:
>

[..]

> The dislike probably comes from how an enum is typically viewed.

Maybe.

> To my knowledge, an enum is typically viewed as an integer with a limited
> set of possible values (that some/most of those values also have a symbol=
ic
> name is incidental).

Yes, whereby this limited set is always a limited range (7.2 p7), see
also below.

> A scoped enum gives you the added value of being able
> to specify the underlying storage.

Correct, but this description does not go far enough. When scoped enums
where proposed it turned out that the specification of an underlying
type should not be restricted to scoped enums and the concept of a
*fixed* underlying type was introduced. so we can now define e.g.

enum Ef : int {};

Ef is an *unscoped* enum with a *fixed* underlying type. But all scoped
enums have essentially a fixed underlying type. If this type is not
explicitly provided, it is int (7.2 p5+6).

> With this view the interpretation of the declarations would be:
>    enum class Widget : unsigned int { list_view, box, button }; /* RESTRI=
CT a
> storage cell of size unsigned int to store only the specified values */

Note that the set of values of any enumeration type with fixed
underlying type is equal to the set of the possible values of the
underlying type (7.2 p7), so your comment seems misleading to me,
because the possible values of Widget are essentially equal to the range

[0, std::numeric_limits<unsigned>::max()]

In other enum cases, the range of enum values is a sub-range possibly
identical to the range of the values of the underlying type.

Before the CD this was not really clear and some implementations did
have a stronger interpretation of this. One of the key issues for
clarifying the intended meaning were the following
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#128http://www.=
open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#172http://www.open-std.or=
g/jtc1/sc22/wg21/docs/cwg_defects.html#628http://www.open-std.org/jtc1/sc22=
/wg21/docs/cwg_defects.html#685http://www.open-std.org/jtc1/sc22/wg21/docs/=
cwg_defects.html#1022http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defect=
s.html#1094

>    enum class SuperWidget : Widget { iconview }; /* EXTEND? the allowed v=
alues
> to include iconview */

I don't know yet, what the meaning should be. For me one intuitive
interpretation would be that SuperWidget has two enumerators of value 0.
An alternative interpretation could be that SuperWidget::iconview has
the numeric value 3 in this example.

We also have to define the rules for the underlying type. My intuitive
understanding would be that SuperWidget still has the same underlying
type of Widget here. This makes sense, because the underlying type for
scoped enums is determined *before* the enumeration values are seen. We
could allow to change the underlying type by some other syntax, e.g.

enum class SuperWidget : Widget, unsigned long long { iconview };

I would guess that only *extending* this underlying type should be
well-formed.

Maybe different people have different preferences and the meaning must
be controllable somehow.

> OTOH, you seem to view a (scoped) enum as its base-type with some of the
> values given a symbolic name:

Is your "base-type" the underlying type? If so, I didn't want to imply
that. The underlying type just defines the "raw storage" layout. For
that reason we have in 7.2 p8:

"Two enumeration types are layout-compatible if they have the same
underlying type."

>    enum class Widget : unsigned int { list_view, box, button }; /* Can st=
ore
> all values of an unsigned int, with three of them given a specific,
> symbolic, name */

Widget has a value range of unsigned int, this is what the standard
defines.

>    enum class SuperWidget : Widget { iconview }; /* Extend the list of
> symbolic names to include iconview */

As described above, I'm not yet sure what the precise meaning should be.

HTH & Greetings from Bremen,

- Daniel Kr=FCgler





--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#280

FromMiles Bader <miles@gnu.org>
Date2011-09-08 14:46 -0700
Message-ID<buo4o0nr2td.fsf@dhlpc061.dev.necel.com>
In reply to#279
=?ISO-8859-15?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.=
com> writes:
> >    enum class Widget : unsigned int { list_view, box, button };
> >    enum class SuperWidget : Widget { iconview };
>
> I don't know yet, what the meaning should be. For me one intuitive
> interpretation would be that SuperWidget has two enumerators of value 0.
> An alternative interpretation could be that SuperWidget::iconview has
> the numeric value 3 in this example.

Surely the latter...

That sort of usage seems very common in existing code, by doing
something like:

   enum X { a, b, X_MAX };
   enum Y { d = X_MAX + 1, e, Y_MAX };

Real inheritance seems like a natural way to sugar this up a bit.

Some other possible behavior:

* when the compiler does type checking of enum classes, consider enum
 classes related by inheritance compatible in some appropriate sense
 (e.g., an enum superclass can be assigned to an enum subclass, enum
 classes related by inheritance can be compared, etc)

* for enum classes, import all the members of the parent into the
 child, e.g.:

   enum class X : whatever { a, b };
   enum class Y : X { d, e };

 would yield X::a = 0, X::b = 1, Y::a = 0, Y::b = 1, Y::d = 2, Y::e = 3.

      [dunno about this one; maybe it's not desirable...]


-Miles

--
`...the Soviet Union was sliding in to an economic collapse so comprehensive
 that in the end its factories produced not goods but bads: finished products
 less valuable than the raw materials they were made from.'  [The Economist]


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#292 — Re: New strongly type enum... why not use "using"?

From"peter miller"<fuchsia.groan@virgin.net>
Date2011-09-12 11:18 -0700
SubjectRe: New strongly type enum... why not use "using"?
Message-ID<op.v1or91r412d93i@deadyawn>
In reply to#280
Hi Miles,

>  That sort of usage seems very common in existing code, by doing
>  something like:
>
>     enum X { a, b, X_MAX };
>     enum Y { d = X_MAX + 1, e, Y_MAX };


It is common. But surely the most C++ way to solve it, is with
a "using" declaration, i.e. change the enumerator-definition
(7.2/1) to be:

_enumerator-definition_:
  _enumerator_
  _enumerator_ = _constant-expression_
  using _enum-key_ _identifier_

so that you can write:

enum Y { using enum X, d, e, Y_max };

and the "using declaration" imports all members of X into Y.

The sensible value of d would be the last value in X, plus one;
but if it's easier for compiler-writers, it could be the highest
value in X, plus one.

This approach also allows me to code:

enum Z { a, b, c };

enum Z_count { using enum Z, Z_MAX };

enum { Z_MAX = Z_count::Z_MAX };

And now I don't pollute Z with Z_MAX - which always seemed
conceptually wrong to me.

Peter

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#293 — Re: New strongly type enum... why not use "using"?

FromMiles Bader<miles@gnu.org>
Date2011-09-13 09:29 -0700
SubjectRe: New strongly type enum... why not use "using"?
Message-ID<buor53lvzoy.fsf@dhlpc061.dev.necel.com>
In reply to#292
"peter miller"<fuchsia.groan@virgin.net>  writes:
>>   That sort of usage seems very common in existing code, by doing
>>   something like:
>>
>>      enum X { a, b, X_MAX };
>>      enum Y { d = X_MAX + 1, e, Y_MAX };
>
>  It is common. But surely the most C++ way to solve it, is with
>  a "using" declaration
...
>  enum Y { using enum X, d, e, Y_max };
>
>  and the "using declaration" imports all members of X into Y.

Hmm, "the most C++ way" is obviously a rather subjective matter.

Using "using" to simply import members from another enum does seem
intuitive enough, but having it change the following enumeration
values, or modify type-checking rules, seems pretty awkward.

It's especially awkward for the type-checking changes I mentioned --
and I think these are very desirable given typical usage -- because
"using ..."  occurs inside the body, so having an effect on the type
as a whole is quite weird [what happens, after all, if you put the
"using ..." at positions other that the beginning, which is something
that the syntax implies is OK, or use "using ..." multiple times?].

The thing is that what people are doing here really _is_ "inheritance",
so using C++'s usual inheritance syntax seems very natural to me.

-Miles

-- 
People who are more than casually interested in computers should have at
least some idea of what the underlying hardware is like.  Otherwise the
programs they write will be pretty weird.  -- Donald Knuth


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#295 — Re: New strongly type enum... why not use "using"?

From"peter miller"<fuchsia.groan@virgin.net>
Date2011-09-15 14:13 -0700
SubjectRe: New strongly type enum... why not use "using"?
Message-ID<op.v1unveap12d93i@deadyawn>
In reply to#293
Miles,

>  Using "using" to simply import members from another enum does
>  seem intuitive enough, but having it change the following
>  enumeration values,

It's no worse than this:

enum A
{
    x,
    y = 7,
    z
};

....and I thought it less surprising than this:

enum B
{
     a, // == 0
     using enum A,
     c, // == 1
};

....since it's just syntactic sugar for this:

enum B
{
     a, // == 0
     x = A::x,
     y = A::y,
     z = A::z,
     c, // == A::z + 1
};


And it has the extra benefit of being able to automatically
"count" the members in an enum. But I don't actually care; the
counter could be left unchanged.

>  or modify type-checking rules, seems pretty awkward.

How does it modify the type checking rules? There are no changes
I can see.

>  It's especially awkward for the type-checking changes I mentionedand I
>  think these are very desirable given typical usage

Actually, as Marcel Muller said, the problem with inheritance
is slicing; for example:

struct base_class { int a; };
struct derived_class : base_class { int b };

void s1(base_class);
void s2(derived_class d) { s1( d ); }
void s3() { s3( derived_class {} ); }

enum class base_enum { a };
enum class derived_enum : base_enum { b };

void f1(base_enum);
void f2(derived_enum d) { f1( d ); }
void f3() { f1( derived_enum::b ); }


The case with enums should be analogous to the case with
classes - if it's just inheritance. When s3() is called,
everything is fine; s1() is handed a sensible copy of
base_class. But what happens when f1() is called?

In my code I can find two cases:

case 1) f1() wouldn't understand the new constants and would
go into an error recovery mode - e.g. throw an exception.

There is no way for it to get a useful value of the "base
enum", as happens with classes.

In this case, inheritance has gained me nothing. (Well, it's
gained me some trouble - sloppy code lacking proper handling
for illegal enum values has become broken. And I don't want
to spend my time reauditing code.)

case 2) The constants are actually bitmasks and f1() would
work fine. In this case, my code already gets inheritance
through meta programming, e.g.

template<typename Enum>
auto
f4(Enum)
->  typename std::enable_if
<
  mpl::has_key<mpl::set<base_enum,derived_enum>,Enum>::value
>  ::type;

(If need be, this can wrap a function in a library.)

I suspect the above will cope with all the valid "inheritance"
cases.

The real problem is manually keeping enums in sync. If I
was in a forward looking mood, then the code would use a
macro, like this:

#define BIT_CONSTANTS bit0 = 1, bit1 = 2, bit2 = 4

enum C { BIT_CONSTANTS };
enum C_with_bells_on { BIT_CONSTANTS, bit3 = 8 };

So a using-declaration inside enums would remove another use of
the preprocessor.

And then there was the extra benefit of being able to
automatically count enum members.

>  -- because
>  "using ..."  occurs inside the body, so having an effect on the type
>  as a whole is quite weird [what happens, after all, if you put the
>  "using ..." at positions other that the beginning, which is something
>  that the syntax implies is OK, or use "using ..." multiple times?].

The obvious thing happens. It's just syntactic sugar/macro
alleviation.

(And if enums inherit, why not multiple enum "inheritance"?)

>  The thing is that what people are doing here really _is_ "inheritance",
>  so using C++'s usual inheritance syntax seems very natural to me.

To repeat what I said above. I can't find a real-world case
where inheritance of enums would do anything I can't already
do - except import identifiers quickly and easily. So that
was the problem I targeted.

Peter


-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#229

FromPete Becker <pete@versatilecoding.com>
Date2011-08-18 07:51 -0600
Message-ID<2011081706332351646-pete@versatilecodingcom>
In reply to#224
On 2011-08-16 21:28:17 +0000, Phil Bouchard said:

> Hi,
>
> Is it too late to change the strongly type enum?

Yes, C++11 has been unanimously approved. It will be an official
standard in a few weeks.

No, work is just starting on the next version of the C++ standard.

>  I have a proposal
> that is much cleaner than what is on its way.
>
> Right now we have:
> enum class Val: unsigned long { E1, E2, E3, E4 };
>
> Comments:
> 1) This design is bad because the ':' sign is reserved for inheritance.

Really? Where does the standard say that it's "reserved"? <g>

It's currently used to indicate inheritance, to separate two
expressions in a ternary operator, and to mark the size of a bitfield.

>
> 2) Inheriting from another enum would be quite useful.  For example:
> enum class Widget {button, combobox, listview};
> enum class SuperWidget : Widget {iconview}
>
> This way iconview would be equal to 3, not 0.

Sure. That's not precluded by using ':' to indicate that an enum is
based on an integral type.

--
 Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#241

FromVictor Bazarov<v.bazarov@comcast.invalid>
Date2011-08-24 14:06 -0700
Message-ID<j2j5v2$uct$1@dont-email.me>
In reply to#229
On 8/18/2011 9:51 AM, Pete Becker wrote:
>  On 2011-08-16 21:28:17 +0000, Phil Bouchard said:
>>  Right now we have:
>>  enum class Val: unsigned long { E1, E2, E3, E4 };
>>
>>  Comments:
>>  1) This design is bad because the ':' sign is reserved for inheritance.
>
>  Really? Where does the standard say that it's "reserved"?<g>
>
>  It's currently used to indicate inheritance, to separate two
>  expressions in a ternary operator, and to mark the size of a bitfield.

..and to designate a symbol as a label (for use in goto), right?  Or has
it been removed from the Standard?

V
-- 
I do not respond to top-posted replies, please don't ask


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#242

FromPaavo Helde<myfirstname@osa.pri.ee>
Date2011-08-24 14:06 -0700
Message-ID<Xns9F45D12A922D5myfirstnameosapriee@216.196.109.131>
In reply to#229
Pete Becker<pete@versatilecoding.com>  wrote in news:2011081706332351646-
pete@versatilecodingcom:

>
>  On 2011-08-16 21:28:17 +0000, Phil Bouchard said:
>>  1) This design is bad because the ':' sign is reserved for inheritance.
>
>  Really? Where does the standard say that it's "reserved"?<g>
>
>  It's currently used to indicate inheritance, to separate two
>  expressions in a ternary operator, and to mark the size of a bitfield.

You are forgetting goto labels!

Cheers
Paavo


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#247

FromFrancis Glassborow<francis.glassborow@btinternet.com>
Date2011-08-24 14:52 -0700
Message-ID<tdWdnShmRNgsH9DTnZ2dnUVZ8qidnZ2d@bt.com>
In reply to#229
On 18/08/2011 14:51, Pete Becker wrote:
>
>  On 2011-08-16 21:28:17 +0000, Phil Bouchard said:
>
>>  Hi,
>>
>>  Is it too late to change the strongly type enum?
>
>  Yes, C++11 has been unanimously approved. It will be an official
>  standard in a few weeks.
>
>  No, work is just starting on the next version of the C++ standard.
>
>>  I have a proposal
>>  that is much cleaner than what is on its way.
>>
>>  Right now we have:
>>  enum class Val: unsigned long { E1, E2, E3, E4 };
>>
>>  Comments:
>>  1) This design is bad because the ':' sign is reserved for inheritance.
>
>  Really? Where does the standard say that it's "reserved"?<g>
>
>  It's currently used to indicate inheritance, to separate two
>  expressions in a ternary operator, and to mark the size of a bitfield.
>

and for a case in a switch statement, and for a label (long time since I
used one of those but I tend to not use goto :)


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#252

FromPhil Bouchard<philippe@fornux.com>
Date2011-08-24 17:39 -0700
Message-ID<4e55797e@news.x-privat.org>
In reply to#247
On 8/24/2011 5:52 PM, Francis Glassborow wrote:
>
>  and for a case in a switch statement, and for a label (long time since I
>  used one of those but I tend to not use goto :)

Bison generates source code having gotos...


-Phil


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#230

FromAlain Ketterlin <alain@dpt-info.u-strasbg.fr>
Date2011-08-18 07:53 -0600
Message-ID<8739gz7pua.fsf@dpt-info.u-strasbg.fr>
In reply to#224
Phil Bouchard <philippe@fornux.com> writes:

> Is it too late to change the strongly type enum?  I have a proposal
> that is much cleaner than what is on its way.

Too late.

> Right now we have:
> enum class Val: unsigned long { E1, E2, E3, E4 };
>
> Comments:
> 1) This design is bad because the ':' sign is reserved for inheritance.

It makes perfect sense to me. Sub-classing is restriction. You define
Val as a restriction of unsigned long to four possible values (and you
give symbolic names to these values to make sure you do not violate the
restriction). A Val "is a" unsigned long.

> 2) Inheriting from another enum would be quite useful.  For example:
> enum class Widget {button, combobox, listview};
> enum class SuperWidget : Widget {iconview}

This contradicts with the meaning of sub-typing, which is restriction,
and which you use here as augmentation. Assigning a value of type
SuperWidget to a variable of type Widget would be forbidden, if I
understand your example correctly. The exact opposite of what happens
between a sub-class and its base-class.

> 3) Redefining the underlying type could be easily done with:
> enum class Val { unsigned long E1, E2, E3, E4 };
>
> This is much more neat and is similar to a declaration of multiple instances:
> const unsigned long E1, E2, E3, E4;

In my opinion, this looks much like a list of members. I know, unions do
this already, but there's "class" in the type declaration here.

-- Alain.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#244

FromPhil Bouchard<philippe@fornux.com>
Date2011-08-24 14:52 -0700
Message-ID<4e4d4889$1@news.x-privat.org>
In reply to#230
On 8/18/2011 9:53 AM, Alain Ketterlin wrote:
>
>>  2) Inheriting from another enum would be quite useful.  For example:
>>  enum class Widget {button, combobox, listview};
>>  enum class SuperWidget : Widget {iconview}
>
>  This contradicts with the meaning of sub-typing, which is restriction,
>  and which you use here as augmentation. Assigning a value of type
>  SuperWidget to a variable of type Widget would be forbidden, if I
>  understand your example correctly. The exact opposite of what happens
>  between a sub-class and its base-class.

Exactly.

>>  3) Redefining the underlying type could be easily done with:
>>  enum class Val { unsigned long E1, E2, E3, E4 };
>>
>>  This is much more neat and is similar to a declaration of multiple instances:
>>  const unsigned long E1, E2, E3, E4;
>
>  In my opinion, this looks much like a list of members. I know, unions do
>  this already, but there's "class" in the type declaration here.

That's what it is, a list of constant members:
const unsigned long E1 = 0, E2 = 1, E3 = 2, E4 = 3;


-Phil


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#231

FromMarcel Müller <news.5.maazl@spamgourmet.com>
Date2011-08-18 07:52 -0600
Message-ID<4e4ba09e$0$6636$9b4e6d93@newsspool2.arcor-online.net>
In reply to#224
Phil Bouchard wrote:
>
> Right now we have:
> enum class Val: unsigned long { E1, E2, E3, E4 };
>
> Comments:
> 1) This design is bad because the ':' sign is reserved for inheritance.

I see no problem so far.

> 2) Inheriting from another enum would be quite useful.  For example:
> enum class Widget {button, combobox, listview};
> enum class SuperWidget : Widget {iconview}
>
> This way iconview would be equal to 3, not 0.

I had the same idea some time ago. However, poeple told me that it is
not that easy.

First of all inheriting from a type implies that slicing is possible.
But SuperWidget can't ever be safely converted to Widget, becuse
Widget can't take the value iconview. In fact it is the other way
around. Widget is Safely a SuperWidget. The covariance/contravariance
is swapped.


> 3) Redefining the underlying type could be easily done with:
> enum class Val { unsigned long E1, E2, E3, E4 };

This implies that the type is specific to each enum constant. It isn't. IMO

 enum class Val: unsigned long

is fine. Val is an unsigned long, but it cannot be implicitly
converted because it is a private base.


Marcel


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#233

FromPhil Bouchard<philippe@fornux.com>
Date2011-08-23 18:20 -0700
Message-ID<4e52bed4$1@news.x-privat.org>
In reply to#231
On 8/18/2011 9:52 AM, Marcel Müller wrote:
>
>>  3) Redefining the underlying type could be easily done with:
>>  enum class Val { unsigned long E1, E2, E3, E4 };
>
>  This implies that the type is specific to each enum constant. It isn't. IMO
>
>  enum class Val: unsigned long
>
>  is fine. Val is an unsigned long, but it cannot be implicitly
>  converted because it is a private base.

I made another mistake.  The bitfields technically should be declared as
follows:
enum class Val { unsigned long E1 : 2, E2 : 2, E3 : 2, E4 : 2 }

I'm sure the syntax could change to the following:
enum class Val { unsigned long E1, E2, E3, E4 : 2 }


-Phil


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


#245

FromPhil Bouchard <philippe@fornux.com>
Date2011-08-24 14:52 -0700
Message-ID<4e503d0f@news.x-privat.org>
In reply to#231
On 8/18/2011 9:52 AM, Marcel Müller wrote:
>
>> 3) Redefining the underlying type could be easily done with:
>> enum class Val { unsigned long E1, E2, E3, E4 };
>
> This implies that the type is specific to each enum constant. It isn't. IMO
>
> enum class Val: unsigned long
>
> is fine. Val is an unsigned long, but it cannot be implicitly
> converted because it is a private base.

(Sorry for the delay but my posts get more than 24 hours to appear).

BTW I just realized that what I was proposing could make use of bitfields also:
enum class Val { unsigned long E1, E2, E3, E4 : 4 };

This way it could be used as such:
struct A
{
       Val v1, v2;
};

Thus:
sizeof(A) would be equal to 8


-Phil


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.std.c++


csiph-web