digitalmars.D.learn - Template for going from Array --> list of args
- Bill Baxter (65/65) Jan 29 2007 Is there any better way to do this than what I've got below?
- Kirk McDonald (19/94) Jan 30 2007 Something like this should work (though I haven't tested it):
- Bill Baxter (6/27) Jan 30 2007 Whoa, didn't realize you could make a variable out of a type tuple. Or
- Frits van Bommel (6/17) Jan 30 2007 Are you sure? 'foreach' with a tuple as aggregate is automatically
- Don Clugston (5/23) Jan 31 2007 I'm almost certain you're right. If inside the loop, you insert asm
- Bill Baxter (3/27) Jan 31 2007 Ok. All's the better then. Thanks to the three of ya.
Is there any better way to do this than what I've got below? The variadic stuff lets you treat lists of args as arrays, but is there some nice way to go the other direction? Take the elements of an array and pass them as individual args? The code below just does a not-so-slick and not-so-exhaustive case-by-case on the number of arguments. Kind of looks reminiscent of the problems variadic templates are supposed to solve, but I can't figure out any way to use variadics to handle this one. ------ template NArgs(alias func) { static if (is(typeof(func) T == function)) { const uint NArgs = T.length; } else { static assert(0, "Not a function with fixed arguments"); } } template callwithN(alias func, alias A) { static if (NArgs!(func)==0) { void callwithN() { func(); } } else static if (NArgs!(func)==1) { void callwithN() { func(A[0]); } } else static if (NArgs!(func)==2) { void callwithN() { func(A[0], A[1]); } } else static if (NArgs!(func)==3) { void callwithN() { func(A[0], A[1], A[2]); } } else static if (NArgs!(func)==4) { void callwithN() { func(A[0], A[1], A[2], A[3]); } } else { static assert(0, "Unsupported number of arguments"); } } void foo(int a, int b) { } void bar(int a, int b, int c) { } void main() { int[5] a=[0,1,2,3,4]; callwithN!(foo,a); callwithN!(bar,a); } ----- What I was thinking was something like: template callwithN(alias func, alias A) { func( array_to_tuple!(NArgs!(func),A) ); } } but that stalled out because any sort of Tuple!(A[0]) type construct bombs saying that A[0] isn't valid as a template argument. --bb
Jan 29 2007
Bill Baxter wrote:Is there any better way to do this than what I've got below? The variadic stuff lets you treat lists of args as arrays, but is there some nice way to go the other direction? Take the elements of an array and pass them as individual args? The code below just does a not-so-slick and not-so-exhaustive case-by-case on the number of arguments. Kind of looks reminiscent of the problems variadic templates are supposed to solve, but I can't figure out any way to use variadics to handle this one. ------ template NArgs(alias func) { static if (is(typeof(func) T == function)) { const uint NArgs = T.length; } else { static assert(0, "Not a function with fixed arguments"); } } template callwithN(alias func, alias A) { static if (NArgs!(func)==0) { void callwithN() { func(); } } else static if (NArgs!(func)==1) { void callwithN() { func(A[0]); } } else static if (NArgs!(func)==2) { void callwithN() { func(A[0], A[1]); } } else static if (NArgs!(func)==3) { void callwithN() { func(A[0], A[1], A[2]); } } else static if (NArgs!(func)==4) { void callwithN() { func(A[0], A[1], A[2], A[3]); } } else { static assert(0, "Unsupported number of arguments"); } } void foo(int a, int b) { } void bar(int a, int b, int c) { } void main() { int[5] a=[0,1,2,3,4]; callwithN!(foo,a); callwithN!(bar,a); } ----- What I was thinking was something like: template callwithN(alias func, alias A) { func( array_to_tuple!(NArgs!(func),A) ); } } but that stalled out because any sort of Tuple!(A[0]) type construct bombs saying that A[0] isn't valid as a template argument. --bbSomething like this should work (though I haven't tested it): import std.traits; void callwith(alias fn, T)(T[] array) { ParameterTypeTuple!(typeof(&fn)) t; foreach (i, e; t) { t[i] = array[i]; } fn(t); } void foo(int a, int b) { } void main() { int[5] a = [0,1,2,3,4]; callwith!(fn, int)(a); } -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 30 2007
Kirk McDonald wrote:Bill Baxter wrote: Something like this should work (though I haven't tested it):Works indeed! Thanks.import std.traits; void callwith(alias fn, T)(T[] array) { ParameterTypeTuple!(typeof(&fn)) t;Whoa, didn't realize you could make a variable out of a type tuple. Or if I did know it once, I completely forgot it.foreach (i, e; t) { t[i] = array[i]; }I guess this squashes any hope of the thing getting inlined... :-(fn(t); } void foo(int a, int b) { } void main() { int[5] a = [0,1,2,3,4]; callwith!(fn, int)(a); }--bb
Jan 30 2007
Bill Baxter wrote:Kirk McDonald wrote:Are you sure? 'foreach' with a tuple as aggregate is automatically unrolled. Sort of a "static foreach", really. So it's not actually a loop. In fact, the index is a compile-time constant. I'm not sure how the compiler handles this, but I suspect the optimizer may not even know it used to be any kind of loop at all...ParameterTypeTuple!(typeof(&fn)) t;Whoa, didn't realize you could make a variable out of a type tuple. Or if I did know it once, I completely forgot it.foreach (i, e; t) { t[i] = array[i]; }I guess this squashes any hope of the thing getting inlined... :-(
Jan 30 2007
Frits van Bommel wrote:Bill Baxter wrote:I'm almost certain you're right. If inside the loop, you insert asm statements, they are placed after each other, with no indication that the loop ever existed. (Makes it possible to write a compile-time compiler that writes directly to asm code...).Kirk McDonald wrote:Are you sure? 'foreach' with a tuple as aggregate is automatically unrolled. Sort of a "static foreach", really. So it's not actually a loop. In fact, the index is a compile-time constant. I'm not sure how the compiler handles this, but I suspect the optimizer may not even know it used to be any kind of loop at all...ParameterTypeTuple!(typeof(&fn)) t;Whoa, didn't realize you could make a variable out of a type tuple. Or if I did know it once, I completely forgot it.foreach (i, e; t) { t[i] = array[i]; }I guess this squashes any hope of the thing getting inlined... :-(
Jan 31 2007
Don Clugston wrote:Frits van Bommel wrote:Ok. All's the better then. Thanks to the three of ya. --bbBill Baxter wrote:I'm almost certain you're right. If inside the loop, you insert asm statements, they are placed after each other, with no indication that the loop ever existed. (Makes it possible to write a compile-time compiler that writes directly to asm code...).Kirk McDonald wrote:Are you sure? 'foreach' with a tuple as aggregate is automatically unrolled. Sort of a "static foreach", really. So it's not actually a loop. In fact, the index is a compile-time constant. I'm not sure how the compiler handles this, but I suspect the optimizer may not even know it used to be any kind of loop at all...ParameterTypeTuple!(typeof(&fn)) t;Whoa, didn't realize you could make a variable out of a type tuple. Or if I did know it once, I completely forgot it.foreach (i, e; t) { t[i] = array[i]; }I guess this squashes any hope of the thing getting inlined... :-(
Jan 31 2007