Implicit enum conversions are a stupid PITA

Yigal Chripun yigal100 at gmail.com
Thu Mar 25 06:33:07 PDT 2010


Regan Heath Wrote:

> yigal chripun wrote:
> > Here's a Java 5 version with D-like syntax: 
> > 
> > enum Flag {
> >     READ  (0x1), WRITE (0x2), OTHER(0x4)
> >     
> >     const int value;
> >     private this (int value) {
> >         this.value = value;
> >      }
> > }
> > 
> >  int main(string[] args) {
> >     foo(FLAG.READ.value);
> >     foo(FLAG.READ.value | FLAG.WRITE.value);
> >     return 0;
> > }
> > 
> > No conversions required. 
> 
> Cool.  I wasn't aware of that Java feature/syntax - shows how much Java 
> I do :p
> 
> But.. what is the definition of 'foo' in the above, specifically does it 
> take an argument of type Flag? or int?
> 

foo's signature in this case would be something like:
void foo(int);


> If the latter, then all you're doing is shifting the conversion.  In my 
> example it was a cast, in the above it's a property called 'value' which 
> converts the "enum" to 'int'.
> 

It might do something very similar but it is not the same semantically. 
by casting the enum member to an int you say something about its identity vs. a value property is just a property.
 For example, I can define a Color Enum that has two properties, an ordinal value and a hex RGB value.



> Interestingly you can do something similar in D...
> 
> import std.stdio;
> 
> struct Enum { this(int v) { value = v; } int value; }
> 
> struct Flag
> {
>    Enum READ  = Enum(1);
>    Enum WRITE = Enum(2);
>    Enum OTHER = Enum(4);
> }
> 
> static Flag FLAG;
> 
> void foo(int flag)
> {
>    writefln("flag = %d", flag);
> }
> 
> void main()
> {
>    foo(FLAG.READ.value);
>    foo(FLAG.READ.value|FLAG.WRITE.value);
> }
> 
> What I really want is something more like...
> 
> import std.stdio;
> import std.string;
> 
> struct Enum
> {
>    int value;
> 
>    this(int v)
>    {
>      value = v;
>    }
> 
>    Enum opBinary(string s:"|")(Enum rhs)
>    {
>      return Enum(value|rhs.value);
>    }
> 
>    const string toString()
>    {
>      return format("%d", value);
>    }
> }
> 
> struct Flag
> {
>    Enum READ  = Enum(1);
>    Enum WRITE = Enum(2);
>    Enum OTHER = Enum(4);
> }
> 
> static Flag FLAG;
> 
> void foo(Enum e)
> {
>    writefln("e = %d", e);
> }
> 
> void main()
> {
>    foo(FLAG.READ);
>    foo(FLAG.READ|FLAG.WRITE);
> }
> 
> This is only a partial implementation, to complete it I would have to 
> manually define all the numeric and logical operators in my Enum struct.
> 
> What I want is for D to do all this with some syntactical sugar, eg.
> 
> enum FLAG : numeric
> {
>    READ = 1, WRITE = 2, OTHER = 4
> }
> 
> R

That's not how it's implemented. the enum members are actually singleton instances of anonymous inner-classes. each member can have it's own methods as well as methods defined for the enum type itself. 
I can have:
enum SolarSystem { Earth(mass, distance_from_sun), ...}
SolarSystem.Earth.rotate();
etc...

You could implement this in D with structs/classes but it'll take a lot of code. Java does this for you.





More information about the Digitalmars-d mailing list