digitalmars.D.learn - Template for going from Array --> list of args
- Bill Baxter <dnewsgroup billbaxter.com> Jan 29 2007
- Kirk McDonald <kirklin.mcdonald gmail.com> Jan 30 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jan 30 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Jan 30 2007
- Don Clugston <dac nospam.com.au> Jan 31 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jan 31 2007
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. --bb
Something 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: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... :-(
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...
Jan 30 2007
Frits van Bommel wrote:Bill Baxter wrote:Kirk McDonald wrote: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... :-(
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...
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...).
Jan 31 2007
Don Clugston wrote:Frits van Bommel wrote:Bill Baxter wrote:Kirk McDonald wrote: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... :-(
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...
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...).
Ok. All's the better then. Thanks to the three of ya. --bb
Jan 31 2007








Bill Baxter <dnewsgroup billbaxter.com>