Thread overview
Templated Enums?
Jun 06, 2012
Era Scarecrow
Jun 06, 2012
Johannes Pfau
Jun 06, 2012
Era Scarecrow
Jun 06, 2012
bearophile
Jun 07, 2012
Era Scarecrow
Jun 07, 2012
Ali Çehreli
June 06, 2012
 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
}
June 06, 2012
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,
    }
}
---------------
June 06, 2012
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.
June 06, 2012
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
June 07, 2012
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 :)
June 07, 2012
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