digitalmars.D.learn - Array to argument list
- Simen Haugen (4/4) Sep 11 2008 I have an array, but I want to send them one by one to a function that
- Jarrett Billingsley (47/51) Sep 11 2008 Hm. My guess is that in general, "no", since you need to know how
- Sergey Gromov (8/30) Sep 11 2008 Obviously it works only for static arrays.
I have an array, but I want to send them one by one to a function that has variadic arguments. Is there a way to do this at runtime? void p(A ...)(A Args) {} p([1, 2, 3]); // I want this to become p(1, 2, 3) somehow...
Sep 11 2008
On Thu, Sep 11, 2008 at 9:39 AM, Simen Haugen <simen norstat.no> wrote:I have an array, but I want to send them one by one to a function that has variadic arguments. Is there a way to do this at runtime? void p(A ...)(A Args) {} p([1, 2, 3]); // I want this to become p(1, 2, 3) somehow...Hm. My guess is that in general, "no", since you need to know how many arguments to call p with at compile time, but you don't know how many you'll need until runtime. You'd have to generate size_t.max instantiations of p to cover all possible array lengths, as well as size_t.max instantiations of a helper function to convert an array into a tuple. However for a restricted case -- fixed-size arrays -- it's possible. But again, the number of instantiations is proportional to the length of the array. Here's an ugly, completely un-transparent solution. import tango.core.Tuple; import tango.io.Stdout; struct Tup(T...) { T vals; } Tup!(T) makeTup(T...)(T args) { Tup!(T) ret; ret.vals = args; return ret; } template Rep(int num, V...) { static if(num == 0) alias Tuple!() Rep; else alias Tuple!(V[0], Rep!(num - 1, V)) Rep; } Tup!(Rep!(N, U)) toTuple(T: U[N], U, int N)(T arr) { Tup!(Rep!(N, U)) ret; foreach(i, v; ret.vals) ret.vals[i] = arr[i]; return ret; } void p(A...)(A args) { foreach(i, arg; args) Stdout.formatln("Arg {}: {}", i, arg); } void main() { int[3] arr = [1, 2, 3]; p(toTuple(arr).vals); }
Sep 11 2008
Simen Haugen <simen norstat.no> wrote:I have an array, but I want to send them one by one to a function that has variadic arguments. Is there a way to do this at runtime? void p(A ...)(A Args) {} p([1, 2, 3]); // I want this to become p(1, 2, 3) somehow...With a bit of template trickery I've got this:import std.stdio; void p(A ...)(A Args) { writeln(A.stringof); writeln(Args[4]); } void PassArrayAsTuple(alias fun, T: E[S], E, size_t S, R...)(T arr, R rest) { static if (S) PassArrayAsTuple!(fun)(cast(E[S-1])arr, arr[$-1], rest); else fun(rest); } void main() { PassArrayAsTuple!(p)("array"); }Obviously it works only for static arrays. I wanted to come up with something like p(ArrayTuple!("array")); but the trick with casting a static array to a smaller static array does not work for template arguments. I'm not sure that it should work for function arguments either, bit it works in DMD 2.019 indeed.
Sep 11 2008