www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Implicit enum conversions are a stupid PITA

reply yigal chripun <yigal100 gmail.com> writes:
Regan Heath Wrote:

 
 One thing being able to convert enum to it's base type does allow is this:
 
 import std.stdio;
 
 enum FLAG
 {
    READ  = 0x1,
    WRITE = 0x2,
    OTHER = 0x4
 }
 
 void foo(FLAG flags)
 {
    writeln("Flags = ", flags);
 }
 
 int main(string[] args)
 {
    foo(FLAG.READ);
    foo(FLAG.READ|FLAG.WRITE);
    return 0;
 }
 
 

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.
Mar 24 2010
parent reply Regan Heath <regan netmail.co.nz> writes:
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? 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'. 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
Mar 25 2010
parent reply Yigal Chripun <yigal100 gmail.com> writes:
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.
Mar 25 2010
next sibling parent Regan Heath <regan netmail.co.nz> writes:
Yigal Chripun wrote:
 You could implement this in D with structs/classes but it'll take a lot of
code. Java does this for you.

My point exactly. R
Mar 25 2010
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Yigal Chripun wrote:
 You could implement this in D with structs/classes but it'll take a lot of
 code. Java does this for you.

That's what templates are for!
Mar 25 2010