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

Ali Çehreli acehreli at yahoo.com
Sun May 31 09:26:35 UTC 2020


On 5/30/20 11:28 PM, mw wrote:
> On Sunday, 31 May 2020 at 00:46:09 UTC, Paul Backus wrote:
>> 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");
> 
>        mixin RW!(string, "z");  // add
> 
>> }
>> ---
> 
> This is better, ... but it breaks std.traits:

The following code solves that I think the following syntax is an 
improvement over Paul Backus's solution because it allows .x instead of 
"x" by taking advantage of a static opDispatch. But it requires 
parenthesis because now it's a string mixin, which is likely to be 
noticeably slow to compile too.

struct RW(T) {
   static string opDispatch(string name)() {
     import std.format;

     return format!q{
       private %s _%s;
       public auto %s() { return _%s; }
       public auto %s(%s val) { _%s = val; return this; }
     }(T.stringof, name,
       name, name,
       name, T.stringof, name);
   }
}

struct Point {
   mixin (RW!int.x);
   mixin (RW!int.y);
     // etc.
}

import std.traits;
import std.stdio;

void main() {
   pragma(msg, FieldNameTuple!(Point));

   auto p = Point(1, 2);
   p.x = 42;
   p.y = 43;
   writeln(p);
}

The spec allows opDispatch to be an eponymous template:

   https://dlang.org/spec/operatoroverloading.html#dispatch

Unfortunately, I could not reach the following cleaner syntax with a 
mixin template:

   mixin RW!int.x;

Ali



More information about the Digitalmars-d-learn mailing list