www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array to argument list

reply Simen Haugen <simen norstat.no> writes:
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
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
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
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
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