A tutorial on D templates

Simen Kjærås simen.kjaras at gmail.com
Mon Jan 16 08:36:25 PST 2012


On Fri, 13 Jan 2012 22:21:52 +0100, Philippe Sigaud  
<philippe.sigaud at gmail.com> wrote:

> There is an 'Examples' section where I show what can be done with  
> templates and there I
> 'borrowed' some code posted here, with attribution. I already exchanged  
> with Andrej
> Mitrovic (thanks!), but also took some code from Timon Gehr, Simen  
> Kjaeraas, Trass3r
> and Jacob Carlborg. Guys, if any of you have a problem with that, tell  
> me so and I'll
> take down the code of course. But if any of you could give me some  
> explanation (a small
> paragraph or two?) about what your code does, I'll be forever grateful :)


The extended enum example does not compile, because you've removed the
unittest{} block around the the tests. I'd say the code in your document
should compile straight out of the box, to be newb-friendly.

As for an explanation:



string EnumDefAsString(T)() if (is(T == enum)) {
     string result = "";
     foreach (e; __traits(allMembers, T))
         result ~= e ~ " = T." ~ e ~ ",";
     return result;
}

This piece of code iterates over all members of the passed enum T,
generating a string containing all members and their values. For
this enum:

   enum bar {
       a, b, c
   }

the generated string looks like this (if you want to check this,
feel free to call EnumDefAsString at run-time and print its result):

   "a = bar.a,b = bar.b,c = bar.c"

As we can see, this is a valid body for an enum. That means we can use
mixin() to generate this exact same enum. But wait - there's more:


template ExtendEnum(T, string s)
     if (is(T == enum) &&
     is(typeof({mixin("enum a{"~s~"}");})))
{
     mixin(
     "enum ExtendEnum {"
     ~ EnumDefAsString!T()
     ~ s
     ~ "}");
}

This code concatenates the string generated from the previous function
with that passed to the function as parameter s. So with bar previously
defined, and this instantiation:

     ExtendEnum!(bar, "d=25")

the body of the function will look like this (after string expansion):



     mixin(
     "enum ExtendEnum {"
     ~ "a = bar.a,b = bar.b,c = bar.c"
     ~ "d=25"
     ~ "}");

concatenating those strings, we see that we have a valid enum definition:

     enum ExtendEnum {a = bar.a,b = bar.b,c = bar.c,d=25}

The mixin then pastes it in, and it is compiled as regular D code.


TLDR:

This code generates an enum definition as a string, by taking all the
members of the old enum, and adding those passed in string parameter s,
and mixing it in.


More information about the Digitalmars-d-learn mailing list