Thread overview
"macro" expansion to build switch case code
Jul 02, 2023
Paul
Jul 02, 2023
nbdusr
Jul 02, 2023
kdevel
Jul 03, 2023
Paul
July 02, 2023

I have a struct similar to the following example. I'd like to build an adder method without having to code the whole method. How do I use the D language to do this? Template, mixins, CTFE..all of them?

struct myS {
    int a, b, c, d, e, f, g, h, i;
    adder(string s, int n) {
        final switch (s) {
            case "aa" :
                a += n; break;
            case "bb" :
                b += n; break;
           ...

Thanks for any assistance.

July 02, 2023

On Sunday, 2 July 2023 at 17:02:44 UTC, Paul wrote:

>

I have a struct similar to the following example. I'd like to build an adder method without having to code the whole method. How do I use the D language to do this? Template, mixins, CTFE..all of them?

struct myS {
    int a, b, c, d, e, f, g, h, i;
    adder(string s, int n) {
        final switch (s) {
            case "aa" :
                a += n; break;
            case "bb" :
                b += n; break;
           ...

Thanks for any assistance.

https://forum.dlang.org/post/rqgvruwgrldklarablii@forum.dlang.org

July 02, 2023

On Sunday, 2 July 2023 at 17:02:44 UTC, Paul wrote:

>

I have a struct similar to the following example. I'd like to build an adder method without having to code the whole method. How do I use the D language to do this? Template, mixins, CTFE..all of them?

struct myS {
    int a, b, c, d, e, f, g, h, i;
    adder(string s, int n) {
        final switch (s) {
            case "aa" :
                a += n; break;
            case "bb" :
                b += n; break;
           ...

Thanks for any assistance.

Thanks for your interesting question!

module mys;
import std.exception;

class UnknownRegister : Exception {
   mixin basicExceptionCtors;
}

enum string [] DefaultRegisterSet = [
      "a", "b", "c", "d", "e", "f", "g", "h", "i"
   ];

struct myS {
   int [string] registers;

   this (string [] register_names)
   {
      foreach (r; register_names)
         registers [r] = 0;
   }

   void adder (string s, int n)
   {
      auto p = s in registers;
      enforce!UnknownRegister (p);
      *p += n;
   }

   int opDispatch (string s) ()
   {
      auto p = s in registers;
      enforce!UnknownRegister (p);
      return *p;
   }
}

unittest {
   auto m = myS (DefaultRegisterSet);
   m.adder ("a", 7);
   m.adder ("a", 8);
   assert (m.a == 15);
   assertThrown!UnknownRegister (m.adder ("j", -1));
   assertThrown!UnknownRegister (m.j == 0);
}
July 02, 2023

On 7/2/23 1:02 PM, Paul wrote:

>

I have a struct similar to the following example.  I'd like to build an adder method without having to code the whole method. How do I use the D language to do this?  Template, mixins, CTFE..all of them?

struct myS {
     int a, b, c, d, e, f, g, h, i;
     adder(string s, int n) {
         final switch (s) {
             case "aa" :
                 a += n; break;
             case "bb" :
                 b += n; break;
            ...

Thanks for any assistance.

Use a static foreach:

import std.traits; // for FieldNameTuple. there are other ways, but this is the most straightforward
switchlabel: // this is needed for break inside a static foreach
final switch(s) {
   static foreach(mem; FieldNameTuple!myS) {
     case mem ~ mem:
        __traits(getMember, this, mem) += n;
        break switchalbel;
   }
}

-Steve

July 03, 2023

On Sunday, 2 July 2023 at 20:27:47 UTC, Steven Schveighoffer wrote:

>

On 7/2/23 1:02 PM, Paul wrote:

>

[...]

Use a static foreach:

import std.traits; // for FieldNameTuple. there are other ways, but this is the most straightforward
switchlabel: // this is needed for break inside a static foreach
final switch(s) {
   static foreach(mem; FieldNameTuple!myS) {
     case mem ~ mem:
        __traits(getMember, this, mem) += n;
        break switchalbel;
   }
}

-Steve

Perfect. Thanks Steve!