Switch with dynamic case
anonymous via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Feb 2 07:01:57 PST 2016
On 02.02.2016 15:07, Daniel Kozak wrote:
> import std.stdio;
> import std.typetuple : TypeTuple;
>
> alias cs = TypeTuple!(0, 1, 2, 3);
>
> void main(string[] argv)
> {
> switch(argv.length)
> {
> default: writeln("Uknown number of args"); break;
> foreach(c; cs)
> {
> case c: writefln("%s args", c);
> break;
> }
> }
> }
>
> This works, but I dont know why or how, is there some documentation
> about this feature?
The key thing to understand is that the foreach is a "static" one. A
static foreach is unrolled at compile-time.
So that switch code is replaced at compile time with this, almost:
----
switch(argv.length)
{
default: writeln("Uknown number of args"); break;
case 0: writefln("%s args", 0);
break;
case 1: writefln("%s args", 1);
break;
case 2: writefln("%s args", 0);
break;
}
----
"But", I hear you ask, "it breaks when I put the default at the bottom.
What's up with that?". Yeah, that's a bit weird/buggy.
The problem is with the break statement. It applies to the foreach, not
to the switch. And while the foreach is unrolled at compile-time, the
break is evaluated at run-time. The generated code really looks more
like this:
----
switch(argv.length)
{
default: writeln("Uknown number of args"); break;
/* start of unrolled foreach */
case 0: writefln("%s args", 0);
goto behind_foreach;
case 1: writefln("%s args", 1);
goto behind_foreach;
case 2: writefln("%s args", 0);
goto behind_foreach;
/* end of unrolled foreach */
behind_foreach:
}
----
So, the breaks skip past the other cases that were created by the
foreach, but they don't actually break out of the switch.
There are at least two open issues related to this:
https://issues.dlang.org/show_bug.cgi?id=14887
https://issues.dlang.org/show_bug.cgi?id=7835
Everything works fine when breaking the switch with a label:
----
sw: switch(argv.length)
{
foreach(c; cs)
{
case c: writefln("%s args", c);
break sw;
}
default: writeln("Uknown number of args"); break;
}
----
Unfortunately, the spec is rather quiet about static foreach. And you
won't actually find the term "static foreach". The only thing I could
find is a little "Foreach over Tuples" section on
<https://dlang.org/spec/statement.html>, which doesn't tell a lot.
More information about the Digitalmars-d-learn
mailing list