www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do I extend an enum?

reply Lass Safin <lasssafin gmail.com> writes:
Why:

enum Base {
     A,
     B,
}

enum Derived : Base {
     C, // Gives error, says it can't implicitly convert 
expression to Base.
     D = 1, // Same error
     E = cast(Base)294, // Finally works. Can only be 
cast(Derived) instead.
}

void func(Derived d) {}

func(Derived.E); // works.
func(Derived.A); // Gives error, says it can't call function with 
Base.A.
func(cast(Derived)Derived.A); // Works.

So, what's the proper way of extending an enum?
Mar 19 2016
next sibling parent reply Lass Safin <lasssafin gmail.com> writes:
On Saturday, 19 March 2016 at 17:40:27 UTC, Lass Safin wrote:
 Why:

 enum Base {
     A,
     B,
 }

 enum Derived : Base {
     C, // Gives error, says it can't implicitly convert 
 expression to Base.
     D = 1, // Same error
     E = cast(Base)294, // Finally works. Can only be 
 cast(Derived) instead.
 }

 void func(Derived d) {}

 func(Derived.E); // works.
 func(Derived.A); // Gives error, says it can't call function 
 with Base.A.
 func(cast(Derived)Derived.A); // Works.

 So, what's the proper way of extending an enum?
Meant "Can also be cast(Derived) instead."
Mar 19 2016
parent JR <sunspyre gmail.com> writes:
On Saturday, 19 March 2016 at 17:41:29 UTC, Lass Safin wrote:
 On Saturday, 19 March 2016 at 17:40:27 UTC, Lass Safin wrote:
 Why:

 enum Base {
     A,
     B,
 }

 enum Derived : Base {
     C, // Gives error, says it can't implicitly convert 
 expression to Base.
     D = 1, // Same error
     E = cast(Base)294, // Finally works. Can only be 
 cast(Derived) instead.
 }

 void func(Derived d) {}

 func(Derived.E); // works.
 func(Derived.A); // Gives error, says it can't call function 
 with Base.A.
 func(cast(Derived)Derived.A); // Works.

 So, what's the proper way of extending an enum?
Meant "Can also be cast(Derived) instead."
"enum B : A" doesn't mean "B extends A", but rather "enum B containing members of type A". Not specifying a type makes it implicitly convertible to int, I think. If you're looking to extend a named enum, I think you have to create a new one. It will become a new type too, though that might not matter. enum Foo { first=123, second=456, third=789 } // int type inferred enum Bar : int { // the ": int" here is important first = Foo.first, // implicit cast to int second = Foo.second, third = Foo.third, fourth = 42, fifth = 0 } If you don't define Bar as having members of type int, it will guess that you want Foo (because we're assigning members with values of Foo's). They would be limited to the range of values Foo offers, and Bar.fourth = 42 is irreconcilabe with that.
Mar 19 2016
prev sibling next sibling parent Simen Kjaeraas <simen.kjaras gmail.com> writes:
On Saturday, 19 March 2016 at 17:40:27 UTC, Lass Safin wrote:
 Why:

 enum Base {
     A,
     B,
 }

 enum Derived : Base {
     C, // Gives error, says it can't implicitly convert 
 expression to Base.
     D = 1, // Same error
     E = cast(Base)294, // Finally works. Can only be 
 cast(Derived) instead.
 }

 void func(Derived d) {}

 func(Derived.E); // works.
 func(Derived.A); // Gives error, says it can't call function 
 with Base.A.
 func(cast(Derived)Derived.A); // Works.

 So, what's the proper way of extending an enum?
There is no way to extend an enum. When you think about it, it's actually the opposite of what you'd generally want. Given two classes: class A {} class B : A {} Every instance of B is a valid A. That is, given a variable of type A, you could assign any B to it. Now consider enums: enum A { x, y, z } enum B : A {} Which values could you put in B? Only those that would be valid for A. That is, only x, y and z. Imagine that we could: enum B : A { w } A foo = B.w; foo now holds a value that is not valid for its type. Hence, you simply cannot. Are there cases where you want to define a new enum that contains all the items in a 'base' enum in addition to some new items? Absolutely, and D lacks a good way to do that. But subtyping would in any case not be the correct way to do it. Are there cases where you want to extend an enum by making a subtype with more items? I would argue that's a strong code smell in D, but I can see why you'd want to. -- Simen
Mar 19 2016
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 19 March 2016 at 17:40:27 UTC, Lass Safin wrote:
 Why:

 enum Base {
     A,
     B,
 }

 enum Derived : Base {
     C, // Gives error, says it can't implicitly convert 
 expression to Base.
     D = 1, // Same error
     E = cast(Base)294, // Finally works. Can only be 
 cast(Derived) instead.
 }

 void func(Derived d) {}

 func(Derived.E); // works.
 func(Derived.A); // Gives error, says it can't call function 
 with Base.A.
 func(cast(Derived)Derived.A); // Works.

 So, what's the proper way of extending an enum?
Look at the grammar: https://dlang.org/spec/enum.html There's no inheritance system for the enums. after the ":" can only be specified the type of the members, aka the "EnumBaseType". " EnumDeclaration: enum Identifier EnumBody enum Identifier : EnumBaseType EnumBody " So when you write enum Derived : Base {} It just means that "Derived" members must be of type "Base" So actually the only thing you can do is to reduce the members count: enum Base {A,B} enum Derived : Base {C = Base.A}
Mar 19 2016