View mode: basic / threaded / horizontal-split · Log in · Help
June 06, 2012
Templated Enums?
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
Re: Templated Enums?
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
Re: Templated Enums?
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
Re: Templated Enums?
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
Re: Templated Enums?
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
Re: Templated Enums?
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
Top | Discussion index | About this forum | D home