Yes maybe
import std.stdio; import std.traits; void foo() { writeln("Do It!"); } void times(T,N)(N n, T action) if (isCallable!T && isIntegral!N) { static if (ParameterTypeTuple!action.length == 1 && isIntegral!(ParameterTypeTuple!action[0])) foreach (i; 0 .. n) action(i); else foreach (i; 0 .. n) action(); } void main(string[] args) { 10.times(&foo); 10.times({writeln("Do It!");}); 10.times((uint n){writeln(n + 1, " Round");}); }
with argument support:
import std.stdio; import std.traits; void foo() { writeln("Do It!"); } struct Step { alias n this; size_t n; this(size_t i) { n = i + 1; } } struct Index { alias n this; size_t n; } void times(T,N,A...)(N n, T action, A args) if (isCallable!T && isIntegral!N) { alias PTTAction = ParameterTypeTuple!action; static if (PTTAction.length >= 1) { alias FP = PTTAction[0]; static if (is(Index == FP) || is(Step == FP)) foreach (i; 0 .. n) action(FP(i), args); else action(args); } else foreach (i; 0 .. n) action(); } void main(string[] args) { 10.times(&foo); 10.times({writeln("Do It!");}); 10.times((Step n){writeln(n, " Step");}); 10.times((Index n, string msg){writeln(n, msg);}, " Index"); stdin.readln; }
UPDATE:
to improve performance, you can use the alias template parameter for the action:
void times(alias action,N)(N n) if (isCallable!action && isIntegral!N) { static if (ParameterTypeTuple!action.length == 1 && isIntegral!(ParameterTypeTuple!action[0])) foreach (i; 0 .. n) action(i); else foreach (i; 0 .. n) action(); } void main(string[] args) { 10.times!(foo); 10.times!({writeln("Do It!");}); 10.times!((uint n){writeln(n + 1, " Round");}); }
Kozzi11
source share