Thread overview
Return enum-templated struct based on runtime value
Apr 05, 2013
Sebastian Graf
Apr 05, 2013
bearophile
Apr 06, 2013
Sebastian Graf
Apr 06, 2013
Tobias Pankrath
Apr 06, 2013
Sebastian Graf
Apr 07, 2013
Tobias Pankrath
April 05, 2013
Hi,

I wonder if there is a good way to dry up this:

    enum Machine
    {
        I386,
        AMD64
        // , ...
    }

    template machineWord(Machine machine)
    {
        static if (machine == Machine.I386)
        {
            alias machineWord = uint;
        }
        static if (machine == Machine.AMD64)
        {
            alias machineWord = ulong;
        }
    }

    ulong foo(Machine machine)
    {
        if (machine == Machine.I386)
        {
            machineWord!(Machine.I386) m = (1 << 32)-1;
            m++;
            return m;
        }
        else // assume AMD64
        {
            machineWord!(Machine.AMD64) m = (1 << 32)-1;
            m++;
            return m;
        }
    }

Essentially, I am doing the same with each machine type, but it has different semantics for each of them. I hope you see this is a valid use case and a way to remove duplication.
Something à la specify the enum members to switch on to a template together with a templated function and then do some compile time magic to expand the code to invoke the appropriate specialization.
April 05, 2013
Sebastian Graf:
> I wonder if there is a good way to dry up this:

I suggest to improve that code a lot.

For machineWord there is:

alias machineWord = Select!(machine == Machine.I386, uint, ulong);


This:
(1 << 32)

Gives:
Error: shift by 32 is outside the range 0..31

Generally it's better to use named enums and final switches, where possible.

Keep in mind built-in integral numbers have the max attribute.

Bye,
bearophile
April 06, 2013
On Friday, 5 April 2013 at 18:00:56 UTC, bearophile wrote:
> Sebastian Graf:
>> I wonder if there is a good way to dry up this:
>
> I suggest to improve that code a lot.
>
> For machineWord there is:
>
> alias machineWord = Select!(machine == Machine.I386, uint, ulong);
>
>
> This:
> (1 << 32)
>
> Gives:
> Error: shift by 32 is outside the range 0..31
>
> Generally it's better to use named enums and final switches, where possible.
>
> Keep in mind built-in integral numbers have the max attribute.
>
> Bye,
> bearophile

Thanks, this shows that I didn't really try to run that example.
The Select template is helpful indeed.

Is there however some way to generate that switch with cases for each enum member in a template, so that each case calls <some-passed-template-func>(Machine)() instantiated with the appropriate enum member? I know you could do it with string mixins, but that be a hassle to implement...

Eventually, I want my code to look like

    void func(Machine machine)() { ... }
    switchOnEachEnumMember!func(machine);
April 06, 2013
>
> Is there however some way to generate that switch with cases for each enum member in a template, so that each case calls <some-passed-template-func>(Machine)() instantiated with the appropriate enum member? I know you could do it with string mixins, but that be a hassle to implement...
>
> Eventually, I want my code to look like
>
>     void func(Machine machine)() { ... }
>     switchOnEachEnumMember!func(machine);

http://dpaste.dzfl.pl/ce8366a7

The foreach is unrolled at compile time.
April 06, 2013
On Saturday, 6 April 2013 at 15:38:55 UTC, Tobias Pankrath wrote:
>>
>> Is there however some way to generate that switch with cases for each enum member in a template, so that each case calls <some-passed-template-func>(Machine)() instantiated with the appropriate enum member? I know you could do it with string mixins, but that be a hassle to implement...
>>
>> Eventually, I want my code to look like
>>
>>    void func(Machine machine)() { ... }
>>    switchOnEachEnumMember!func(machine);
>
> http://dpaste.dzfl.pl/ce8366a7
>
> The foreach is unrolled at compile time.
Perfect! So that's a final switch...
April 07, 2013
On Saturday, 6 April 2013 at 20:35:54 UTC, Sebastian Graf wrote:
> On Saturday, 6 April 2013 at 15:38:55 UTC, Tobias Pankrath wrote:
>>>
>>> Is there however some way to generate that switch with cases for each enum member in a template, so that each case calls <some-passed-template-func>(Machine)() instantiated with the appropriate enum member? I know you could do it with string mixins, but that be a hassle to implement...
>>>
>>> Eventually, I want my code to look like
>>>
>>>   void func(Machine machine)() { ... }
>>>   switchOnEachEnumMember!func(machine);
>>
>> http://dpaste.dzfl.pl/ce8366a7
>>
>> The foreach is unrolled at compile time.
> Perfect! So that's a final switch...

The final switch isn't important here. You could use a normal switch with a default block instead.