how to achieve C's Token Pasting (##) Operator to generate variable name in D?

Paul Backus snarwin at gmail.com
Sun May 31 00:46:09 UTC 2020


On Saturday, 30 May 2020 at 23:39:31 UTC, mw wrote:
>
> Thank you all for the reply.
>
> I hate to write boilerplate code:
>
> class Point {
>   private   int _x;
>   public    int  x()      {return _x;}
>   public  Point  x(int v) {_x=v; return this;}
>
>   ...
>   // ... y, z
> }
>
>
> this is what I've got:
> $ cat b.d
> --------------------------------------------------------------------------------
> // dmd -unittest -vcg-ast -c b.d
> import std.format;
>
>
> enum RW(string T, string name) =
>   format(q{
>     private %1$s _%2$s;
>     public  %1$s  %2$s()        {return _%2$s;}
>     public  auto  %2$s(%1$s v)  {_%2$s = v;  return this;}
>   }, T, name);
>
>
> class Point {
>   mixin(RW!("int",     "x"));
>   mixin(RW!("double",  "y"));
>   mixin(RW!("string",  "z"));
> }
[...]
> Is there a better way to achieve this? esp. for the type `int`, 
> is there any way I don't have to quote it as string?
>
> Thanks.

You can simplify this considerably using a mixin template [1]:

---
mixin template RW(T, string name) {
     private T var;
     public T get() { return var; }
     public typeof(this) set(T val) { var = val; return this; }

     mixin("private alias _", name, " = var;");
     // two aliases with the same name create an overload set
     mixin("public alias ", name, " = get;");
     mixin("public alias ", name, " = set;");
}

class Point {
     mixin RW!(int, "x");
     mixin RW!(int, "y");
     // etc.
}
---

You still need string mixins to make the names work, but the rest 
can be done without them. Large string mixins tend to be 
error-prone and difficult to debug, so it's usually a good idea 
to make them as small as you reasonably can [2].

[1] https://dlang.org/spec/template-mixin.html
[2] http://www.arsdnet.net/this-week-in-d/2016-feb-21.html


More information about the Digitalmars-d-learn mailing list