www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Return enum-templated struct based on runtime value

reply "Sebastian Graf" <SebastianGraf t-online.de> writes:
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.
Apr 05 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
Apr 05 2013
parent reply "Sebastian Graf" <SebastianGraf t-online.de> writes:
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);
Apr 06 2013
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
 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.
Apr 06 2013
parent reply "Sebastian Graf " <Sebastiangraf t-online.de> writes:
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...
Apr 06 2013
parent "Tobias Pankrath" <tobias pankrath.net> writes:
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.
Apr 07 2013