creating a variadic interface
Artur Skawina
art.08.09 at gmail.com
Mon Jul 8 06:01:15 PDT 2013
On 07/08/13 13:25, JS wrote:
> mixin template a(T...)
> {
> template b(TT...)
> {
> static string eval()
> {
> string s;
> int i = 0;
> foreach(t; TT)
> s = "@property "~(t).stringof~" Name"~to!string(i++)~"();\n";
> return s;
> }
> enum b = eval();
> }
>
> mixin("mixin(b!T);");
>
> }
It won't work if one of the types isn't already available inside the
template - the .stringof will give you the name, but the mixin
will fail; to avoid this you can use `T[0]` etc as the type directly,
w/o stringifying.
Something like this would also work:
template evalExpMap(string C, string F, A...) {
enum evalExpMap = {
import std.array, std.conv;
string s, l;
static if (is(typeof(A))) alias B = typeof(A);
else alias B = A;
foreach (I, _; B) {
auto r = replace( replace(F, "%s", A[I].stringof),
"%d", to!string(I));
l ~= (I?", ":"") ~ r;
s ~= r ~ ";\n";
}
return replace(replace(C, "%...;", s), "%...", l);
}();
}
interface A(T, S...) {
mixin(evalExpMap!(q{%...;}, q{@property S[%d]/*%s*/ property%d()}, S));
}
class C : A!(int, long, string) { /* Needs `propertyN` implementations. */ }
It expands to:
interface A(T, S...) {
@property S[0]/*long*/ property0();
@property S[1]/*string*/ property1();
}
and is more readable (once one knows what that helper does ;) ).
In real code, the property names may need to be more configurable;
but I'm not sure what you want to use this for. The helper rewrites
every "%s" pattern -> type-name and every "%d" -> index; maybe that
is enough.
artur
More information about the Digitalmars-d-learn
mailing list