www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templated Enums?

reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
  I've come across an interesting problem. You can template quite 
a few items, but not enums? Some thoughts from the experts would 
likely be nice. Consider...

enum(T) X{ //syntax error
     bitsPerT = T.sizeof * 8,
     //further calculation types can follow
}

assert(X!(byte).bitsPerT == 8);

The compile complains outright you can't do this, but enclosing 
it in a struct makes that problem go away with the same results.

struct(T) X {
     enum {
         bitsPerT = T.sizeof * 8,
     }
}

assert(X!(byte).bitsPerT == 8); //compiles and works

Now obviously X!(byte).bitsPerT is a mouthful, and although alias 
can condense the code, using different inner members require 
unique names, With does a simpler job in a smaller more compact 
scope.

alias X!(byte) bitsPerByte; //unique name unless small scope

assert(bitsPerByte == 8);

with(X!(int)) {
   assert(bitsPerT == 32);
}

  Unfortunately properties (static functions) don't work with this.

struct(T) X {
      property static T plusOne(T i) {return i + 1;}
}

with(X!int) {
     int x;
     writeln(x.plusOne);  //error: plusOne function/template not 
defined...
     writeln(plusOne(x)); //works
}
Jun 06 2012
parent reply Johannes Pfau <nospam example.com> writes:
Am Wed, 06 Jun 2012 21:01:21 +0200
schrieb "Era Scarecrow" <rtcvb32 yahoo.com>:

   I've come across an interesting problem. You can template quite 
 a few items, but not enums? Some thoughts from the experts would 
 likely be nice. Consider...
 
 enum(T) X{ //syntax error
      bitsPerT = T.sizeof * 8,
      //further calculation types can follow
 }
 
 assert(X!(byte).bitsPerT == 8);
 
 The compile complains outright you can't do this, but enclosing 
 it in a struct makes that problem go away with the same results.
 
 struct(T) X {
      enum {
          bitsPerT = T.sizeof * 8,
      }
 }
 
 assert(X!(byte).bitsPerT == 8); //compiles and works
 
According to http://dlang.org/template.html something like this: --------------- class Bar(T) { T member; } --------------- is actually only syntactic sugar for this: --------------- template Bar(T) { class Bar { T member; } } --------------- So instead of --------------- enum(T) X { bitsPerT = T.sizeof * 8, } --------------- it should be possible to do this: --------------- template X(T) { enum X { bitsPerT = T.sizeof * 8, } } ---------------
Jun 06 2012
next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 6 June 2012 at 19:27:25 UTC, Johannes Pfau wrote:
 Am Wed, 06 Jun 2012 21:01:21 +0200
 schrieb "Era Scarecrow" <rtcvb32 yahoo.com>:
 According to http://dlang.org/template.html
 something like this:
 ---------------
 class Bar(T) { T member; }
 ---------------

 is actually only syntactic sugar for this:
 ---------------
 template Bar(T) { class Bar { T member; } }
 ---------------

 So instead of
 ---------------
 enum(T) X
 {
      bitsPerT = T.sizeof * 8,
 }
 ---------------

 it should be possible to do this:
 ---------------
 template X(T)
 {
     enum X
     {
         bitsPerT = T.sizeof * 8,
     }
 }
 ---------------
Interesting... I was wondering that as well, however I don't fully understand templates; those and tuples. I'm sure I'll grok it all eventually.
Jun 06 2012
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Johannes Pfau:

 it should be possible to do this:
 ---------------
 template X(T)
 {
     enum X
     {
         bitsPerT = T.sizeof * 8,
     }
 }
That seems correct, this works: template Foo(T) { enum Foo { bitsPerT = T.sizeof * 8, } } void main() { pragma(msg, Foo!int.bitsPerT); } So if template Foo(T){enum Foo{}} works, then I think it should also work the enum Foo(T){} syntax. So far I don't think I have had to use templated enums, but if other people have such need, than this thread and this post have enough material for a little enhancement request. Bye, bearophile
Jun 06 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 6 June 2012 at 20:52:14 UTC, bearophile wrote:
 That seems correct, this works:

 template Foo(T) {
    enum Foo {
        bitsPerT = T.sizeof * 8,
    }
 }
 void main() {
     pragma(msg, Foo!int.bitsPerT);
 }


 So if template Foo(T){enum Foo{}} works, then I think it should 
 also work the enum Foo(T){} syntax.

 So far I don't think I have had to use templated enums, but if 
 other people have such need, than this thread and this post 
 have enough material for a little enhancement request.
Well if it was only 1-2 value I wouldn't probably have bothered. However when there are several flags enums and values that are calculated based on eachother and used together; I wouldn't want to write enums manually for each type. Seems I'm being thrown now into the deep end of templates and constraints and traits and trying to fully understand it enough to use it all. What an exciting time to be alive :)
Jun 06 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/06/2012 05:33 PM, Era Scarecrow wrote:
 On Wednesday, 6 June 2012 at 20:52:14 UTC, bearophile wrote:
 That seems correct, this works:

 template Foo(T) {
 enum Foo {
 bitsPerT = T.sizeof * 8,
 }
 }
 void main() {
 pragma(msg, Foo!int.bitsPerT);
 }


 So if template Foo(T){enum Foo{}} works, then I think it should also
 work the enum Foo(T){} syntax.

 So far I don't think I have had to use templated enums, but if other
 people have such need, than this thread and this post have enough
 material for a little enhancement request.
Well if it was only 1-2 value I wouldn't probably have bothered. However when there are several flags enums and values that are calculated based on eachother and used together; I wouldn't want to write enums manually for each type. Seems I'm being thrown now into the deep end of templates and constraints and traits and trying to fully understand it enough to use it all. What an exciting time to be alive :)
As far as I understand, this is all you need: template bitsPer(T) { static if (is (T ClassType == class)) { enum bitsPer = __traits(classInstanceSize, ClassType) * 8; } else { enum bitsPer = T.sizeof * 8; } } class C { int[10] a; } void main() { static assert(bitsPer!byte == 8); static assert(bitsPer!int == 32); static assert(bitsPer!C == 448); } Other specializations of bitsPer may be needed. Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
Jun 06 2012