Jason Spencer: > I nievely went and replaced "foreach (t; Iota!(str_types.length))" > with "foreach (t; str_types.length)", since the length of that array > is known at compile-time. That of course bombed, but I don't quite > get why. Is the compiler actually evaluating the foreach loop at > compile time? How could it, when the body makes run-time checks? If > it's not, why doesn't my change work?
foreach (t; str_types.length) doesn't work because integral values are not iterable. You need a range, collection or tuple. foreach (t; 0 .. str_types.length) doesn't work in that code because it's a run-time foreach. The Iota!(n) creates a tuple of the values 0, 1, 2 ... n-1. The foreach done on a tuple is a static foreach, it's done at compile-time, so my code is a way to perform a compile-time unrolling of the if-goto body. You can see it with this example (normally DMD is not able to perform loop unrolling): import std.typetuple: TypeTuple; import std.c.stdio: printf; template Iota(int stop) { static if (stop <= 0) alias TypeTuple!() Iota; else alias TypeTuple!(Iota!(stop-1), stop-1) Iota; } void main() { foreach (i; Iota!(5)) { enum int n = i; printf("%d\n", n); } } The resulting asm: __Dmain comdat push EBX push 0 mov EAX,offset FLAT:_DATA push EAX call near ptr _printf add ESP,8 push 1 mov ECX,offset FLAT:_DATA push ECX call near ptr _printf add ESP,8 push 2 mov EDX,offset FLAT:_DATA push EDX call near ptr _printf add ESP,8 push 3 mov EBX,offset FLAT:_DATA push EBX call near ptr _printf add ESP,8 push 4 push EBX call near ptr _printf add ESP,8 xor EAX,EAX pop EBX ret I suggest you to use a variant of my last version of the code because it contains some asserts and static asserts that improve code safety a bit. See also this enhancement request of mine: http://d.puremagic.com/issues/show_bug.cgi?id=4085 Bye, bearophile