tags:

views:

695

answers:

4

Is there a way in C++ to extend/"inherit" enums?

I.E:

enum Enum {A,B,C};
enum EnumEx : public Enum {D,E,F};

or at least define a conversion between them?

+2  A: 

Not that I know of.

the_drow
A: 

The following code works well.

enum Enum {A,B,C};
enum EnumEx {D=C+1,E,F};
Alexey Malistov
Doesn't really work. A is still an Enum and not an EnumEx. I.e. EnumEx x = A; will fail to compile without a cast.
jon hanson
Actually, I am more concerned about the implications on the type-system, rather than the indexing of the values.
cvb
+3  A: 

If you were able to create a subclass of an enum it'd have to work the other way around.

The set of instances in a sub-class is a subset of the instances in the super-class. Think about the standard "Shape" example. The Shape class represents the set of all Shapes. The Circle class, its subclass, represents the subset of Shapes that are Circles.

So to be consistent, a subclass of an enum would have to contain a subset of the elements in the enum it inherits from.

(And no, C++ doesn't support this.)

Laurence Gonsalves
That's a very specific interpretation of inheritance, that doesn't necessarily apply to all uses of inheritance. I don't think it really explains why a compiler couldn't support enum EnumEx : public Enum {D,E,F}; such that an EnumEx could be passed to a function expecting an Enum.
jon hanson
@jon: because it would break the Liskov substitution principle: D would "be an" Enum (because it inherits from it), but it wouldn't have any of the valid values of an Enum. Contradiction. enums are designed to be "enumerated types" - the whole point is that you define the type by defining all valid objects of that type (in the case of C/C++, actually the map from listed values to all valid types is a bit weird, and involves the type used to represent the enum). This may be a very specific interpretation of inheritance, but it's a good one, and AFAIK it informs the design of C++.
Steve Jessop
As a particular example where it would break, suppose I define an `enum A {1, 65525};` and the compiler decides to use a 16bit unsigned int to represent it. Now suppose I define `enumEx : public Enum { 131071 };`. There's no way this object of type EnumEx can be passed as an instance of Enum, it would in effect be sliced. Oops. This is why you need pointers in C++ to do runtime polymorphism. I guess C++ could make every enum the size of the largest possible enum. But conceptually speaking, the value 131071 should not be a valid instance of Enum.
Steve Jessop
What you actually want when you "extend an enum", probably, is to pass an Enum to a function expecting an EnumEx. As Laurence says, this is the other way around from usual inheritance, and it's not at all clear that inheritance is a good model for it. enums are bad enough as they are, without C++ muddling things further with a version of inheritance that's different from class inheritance.
Steve Jessop
+10  A: 

No, there is not.

enum are really the poor thing in C++, and that's unfortunate of course.

Even the class enum introduced in C++0x does not address this extensibility issue (though they do some things for type safety at least).

The only advantage of enum is that they do not exist: they offer some type safety while not imposing any runtime overhead as they are substituted by the compiler directly.

If you want such a beast, you'll have to work yourself:

  • create a class MyEnum, that contains an int (basically)
  • create named constructors for each of the interesting values

you may now extend your class (adding named constructors) at will...

That's a workaround though, I have never found a satistifying way of dealing with an enumeration...

Matthieu M.
Alas, I agree. So many time I have wanted a type safe way of passing flags etc. but enums are really just ints.
Dr. Tim