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