digitalmars.D.learn - Templates, varargs and static foreach
- %u (16/16) Jan 14 2007 I would like to do the following:
- Kirk McDonald (22/43) Jan 14 2007 There is a "static foreach," only you do not use the "static" keyword.
I would like to do the following: void foo() {} void bar(int a) { foo(); } // 1 void bar(int a, int b) { foo(); foo(); } // 2 void bar(int a, int b, int c) { foo(); foo(); foo(); } // 3 void bar(int[] a) { foreach(b; a) foo(); } // 4 The forms 1-3 should be called, when the amount of arguments is known at compile time. Otherwise 4 is called. Ok - this is a major simplification of the design I'm using. I would like to shorten it using templates. I have tried this: void foo() {} void bar(A...)(A a) { foo(); static if (a.length > 1) { bar(a[1..length]); } void bar(A)(A[] a) { foreach(t;a) foo(); } The problem is that the recursion happens on runtime (unless I specify -O -release -inline). Can the compiler guarantee that the recursion is unfolded, when all those optimizations are on or is there a static for/foreach for doing this in a better way.
Jan 14 2007
%u wrote:I would like to do the following: void foo() {} void bar(int a) { foo(); } // 1 void bar(int a, int b) { foo(); foo(); } // 2 void bar(int a, int b, int c) { foo(); foo(); foo(); } // 3 void bar(int[] a) { foreach(b; a) foo(); } // 4 The forms 1-3 should be called, when the amount of arguments is known at compile time. Otherwise 4 is called. Ok - this is a major simplification of the design I'm using. I would like to shorten it using templates. I have tried this: void foo() {} void bar(A...)(A a) { foo(); static if (a.length > 1) { bar(a[1..length]); } void bar(A)(A[] a) { foreach(t;a) foo(); } The problem is that the recursion happens on runtime (unless I specify -O -release -inline). Can the compiler guarantee that the recursion is unfolded, when all those optimizations are on or is there a static for/foreach for doing this in a better way.There is a "static foreach," only you do not use the "static" keyword. void foo() {} void bar(A...)(A a) { foreach(e; a) { foo(); } } You could also do this at runtime, using D's typesafe variadics: void bar(int[] a...) { foreach(e; a) { foo(); } } Both forms of bar are called in exactly the same way, with the caveat that the latter only accepts int arguments, while the former will accept any arguments. bar(1, 2, 3, 4); -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 14 2007
There is a "static foreach," only you do not use the "static" keyword.void foo() {} void bar(A...)(A a) { foreach(e; a) { foo(); } }Dear Kirk, I tried this too, but disassembling to code reveals that the foreach generates extra instructions when compared to this (dmd 1.00 linux): void bar(A...)(A a) { static if (a.length>0) foo(); static if (a.length>1) foo(); static if (a.length>2) foo(); static if (a.length>3) foo(); ... } I tried this without any optimizations. I just want to be sure that the compiler guarantees the behaviour at compile time. This function is time critical.
Jan 14 2007
Dear Kirk, I tried this too, but disassembling to code reveals that the foreach generates extra instructions when compared to this (dmd 1.00 linux):The optimizer eliminates the extra code - not a problem anymore. I just wondered, why doesn't it do it all on compile time. Here's the dumbobj output: static if's: 0: 55 push %ebp 1: 8b ec mov %esp,%ebp 3: e8 fc ff ff ff call 4 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x4> 8: e8 fc ff ff ff call 9 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x9> d: e8 fc ff ff ff call e <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0xe> 12: e8 fc ff ff ff call 13 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x13> 17: 5d pop %ebp 18: c2 0c 00 ret $0xc 1b: 90 nop foreach: 0: 55 push %ebp 1: 8b ec mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 53 push %ebx 7: 89 45 fc mov %eax,0xfffffffc(%ebp) a: 8b 4d 10 mov 0x10(%ebp),%ecx d: e8 fc ff ff ff call e <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0xe> 12: 8b 45 0c mov 0xc(%ebp),%eax 15: e8 fc ff ff ff call 16 <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x16> 1a: 8b 55 08 mov 0x8(%ebp),%edx 1d: e8 fc ff ff ff call 1e <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x1e> 22: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 25: e8 fc ff ff ff call 26 <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x26> 2a: 5b pop %ebx 2b: c9 leave 2c: c2 0c 00 ret $0xc 2f: 90 nop
Jan 14 2007