How to use labeled break in static foreach?

Steven Schveighoffer schveiguy at gmail.com
Fri Feb 14 14:57:43 UTC 2020


On 2/14/20 1:41 AM, cc wrote:
> import std.meta;
> enum A = AliasSeq!(1, 2, 3, 4);
> THREELOOP: static foreach (idx, field; A) {
>      static if (field == 3) {
>          pragma(msg, "Got a 3!");
>          break THREELOOP;
>      }
>      static if (idx == A.length - 1) {
>          static assert(0, "Got no 3...");
>      }
> }
> 
> What I'd like to achieve in this example is for compilation to fail if 
> the given tuple doesn't contain a matching item.  Is there an easy way 
> to do this?  Trying to break out of the static foreach gives me
> Error:enclosing label `THREELOOP` for `break` not found
> 
> In this reduced example, I was able to accomplish this by setting some 
> enum within the successful comparison body and then checking e.g. static 
> if (!__traits(compiles, FOUND)) but this breaks down once I start 
> dealing with multiple levels of scope.

static foreach does not support break. Partly because the places where 
static foreach is allowed do not allow break statements. In your example 
above, if you are not in a function context, a break statement is not 
allowed. Note that a naked break statement inside a static foreach 
that's inside e.g. a switch statement needs a label to ensure the user 
understands they are breaking the switch, not the static foreach.

foreach does allow breaks. If you use foreach on an AliasSeq, it will 
work. But again, you must be in a function context.

But remember that static foreach and foreach implement all the bodies 
given. So every single one has to be compiled, even if it's not used. 
This can cause problems for things like return statements that make 
further code not executable.

AND static foreach doesn't introduce a new scope (foreach does). Other 
than recursive templates, I can't think of a great way to do this. Your 
enum solution has limits, as you say.

-Steve


More information about the Digitalmars-d-learn mailing list