July 07, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Strakhov | On 07/06/13 21:39, Max Strakhov wrote: > > If anyine has any ideas how make this implementation simplier, bring it on :) Well, you could just use the pseudo-code version that you posted, almost verbatim: > string res = ""; > for(i, rev v; args) > res ~= string.format(", f(args[%d]).val()"); > mixin("return G(" ~ res ~ ");"); > > Only without any actual looping and variables, so compiler could deal with it. auto F(A...)(string format, A args) { mixin({ string res; foreach (I, _; A) res ~= (I?", ":"") ~ "conv(args["~I.stringof~"])"; return "return G(convformat(format), " ~ res ~ ");"; }()); } The compiler can deal with this, no need to make it more complicated. It's a good idea for non-obvious text-as-code manipulations to be explicit, so I'd actually do it like that. A problem when manipulating source code directly is that not everything can be referred to by name - a non-local type or symbol which isn't available in the current scope will work when it's a template parameter or via typeof(), but you can't directly name it and then mix it back in. Locals, including function args, will work though. For cases where the above restriction isn't a problem, we could use something more generic, that will make it possible to solve your problem with a one-liner. It will work with not just "argument-packs" (ie arg-tuples), but also some symbols, types and statically evaluable expressions. The "oops" line shows what does *not* work and why these kinds of mixin tricks should be used only when you have control over all args and users. template evalExpMap(string C, string F, A...) { enum evalExpMap = { import std.array; string s; static if (is(typeof(A))) alias B = typeof(A); else alias B = A; foreach (I, _; B) s ~= (I?", ":"") ~ replace(F, "%", A[I].stringof); return replace(C, "%", s); }(); } import std.stdio; void main() { auto c = mixin (evalExpMap!(q{ foo(%) }, q{ getArray(%)[] }, 1, "two", 3.14)); b1(c, 3_000_000_000u, 2.14, -43L); auto s = S!(int, float, "/4", "blah")(); writeln(typeof(s.data).stringof, typeof(s.blah).stringof); //auto oops = S!(typeof(as()), float, "/4", "blah")(); } auto getArray(T)(T n) { T[2] data = n; return data; } auto foo(A...)(A args) { int c; foreach (rs; args) foreach (v; rs) ++c, write(v, " "); return c; } void b1(T...)(T values) { mixin (evalExpMap!(q{b2('\n',1,2,3,%);}, q{%+1}, values)); } void b2(T...)(T vs) { foreach (v; vs) writeln(v); } template Q(A...) { alias Q=A; } struct S(A...) { mixin (evalExpMap!(q{alias T=Q!(%);}, q{%[16]}, A[0..$-2])); T data; mixin (evalExpMap!(q{Q!(%) }~A[3]~q{;}, q{%[16}~A[$-2]~q{]}, const A[1], shared(A[0])*)); } auto as() { struct An {} return An(); } artur |
Copyright © 1999-2021 by the D Language Foundation