digitalmars.D.learn - Array to argument list
- Simen Haugen <simen norstat.no> Sep 11 2008
- "Jarrett Billingsley" <jarrett.billingsley gmail.com> Sep 11 2008
- Sergey Gromov <snake.scaly gmail.com> Sep 11 2008
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









"Jarrett Billingsley" <jarrett.billingsley gmail.com> 