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

Ali Çehreli acehreli at yahoo.com
Sun May 31 21:20:35 UTC 2020


On 5/31/20 1:00 PM, mw wrote:> On Sunday, 31 May 2020 at 09:37:24 UTC, 
Ali Çehreli wrote:

 > One question: in Sebastiaan's solution opDispatch is performed at
 > run-time

Templates don't exist at run time. They are used for generating code at 
compile time and that's it.

opDispatch is a template. Like all templates, it's evaluated at compile 
time and code is generated for it at compile time. However, if 
opDispatch() is a member function template, then there will be a 
function call execution at runtime but this is not different from any 
other member function call.

Here is a struct with an opDispatch() used as a member function template.

struct XmlElement {
   static opDispatch(string tag)(string value) {
     import std.range;
     import std.format;

     enum opening = format!"<%s>"(tag);
     enum closing = format!"</%s>"(tag);

     // Note: Although we return a chained range, this could return a
     // string[3] as well, which may possibly be more performant.
     return chain(opening, value, closing);
   }
}

import std.stdio;

void main() {
   writeln(XmlElement.foo("hello"));
   writeln(XmlElement.bar("world"));
}

opDispatch() is instantiated with two strings in the program: "foo" and 
"bar". As a result, the XmlElement struct will be the equivalent of the 
following one:

struct XmlElement {
   static foo(string value) {
     enum opening = "<foo>";
     enum closing = "</foo>";
     return chain(opening, value, closing);
   }

   static bar(string value) {
     enum opening = "<bar>";
     enum closing = "</bar>";
     return chain(opening, value, closing);
   }
}

Note how two member functions are added to XmlElement and all of the 
'opening' and 'closing' strings are computed at compile time.

In my solution opDispatch() boils down to a "mixin template" itself. As 
Paul Backus's code does, that mixin template is used for adding the 
following members to the struct for each instantiation of opDispatch(). 
For example, for x, the struct will gain the following template 
definition. (_FOR_X is my annotation).

     mixin template opDispatch_FOR_X(alias code = codeImpl()) {
         private int _x;
         public auto x() { return _x; }
         public auto x(T val) { _x = val; return this; }
     }

Note that each instance of opDispatch() for "x", "y", etc. will gain a 
template definition. Those definitions are a compile-time cost. 
Eventually, when user code mixes-in the corresponding template, then the 
three member above will be added to the user's struct.

After that, there is no run-time cost more than adding those members by 
hand.

Ali




More information about the Digitalmars-d-learn mailing list