Take the 2-minute tour ×


This question follows from this one : The named loop idiom : dangerous?. For people who don't want to read the original question, it was about doing things like that :

named(label1) for(int i = 0 ; i < 10 ; i++) {
            break(label1); // exit outer loop

This new question is about an improved version of the "named loop" idiom. If you're too lazy to read this entire post, you can directly go to the "Example" section of this post to clearly understand what I'm talking about.

Design flaws

Unfortunately, the question was closed very quickly (and later has been re-opened) because it was more a pros/cons debate than a pure technical question. It seems that it was not fitting the SO Q&A format. Moreover, the code I presented had several flaws :

  • The keyword break was redefined by a macro
  • The macro were written using lowercase letters
  • It made some horrible things compilable (at least using MSVC) :

    int foo() {
              break(label1);  // here it's ok, the behavior is obvious
       break(label1); // it compiles fine without warning... but the behavior is pretty obscur!
  • It could break some good-looking code. For instance, the following is not compiling because of a scoping problem.

    int foo() {
           named(label2)  for(int j = 0 ; j < 10 ; j++)
                cout << i*j << endl;

A safer implementation

I tried to fix all these problems in order to get a safe version of named loops. More generally, it could also be called breakable scopes because it can be used to exit prematurely any scope, not only loops.

Here is the definition of the two macros NAMED and BREAK :

    #define NAMED(bn)   if(const bool _YOU_CANNOT_USE_NAMED_BREAK_IF_YOU_ARE_OUTSIDE_##bn##_ = true)\
                            goto _named_loop_identifier__##bn##_;\
                                if(! _YOU_CANNOT_USE_NAMED_BREAK_IF_YOU_ARE_OUTSIDE_##bn##_)\
                                    goto _break_the_loop_labelled_##bn##_;\

    #define BREAK(bn) if(!_YOU_CANNOT_USE_NAMED_BREAK_IF_YOU_ARE_OUTSIDE_##bn##_){} \
                        else goto _break_the_loop_labelled_##bn##_

It looks ugly & cumbersome because it also avoids some warnings that could be generated by MSVC or GCC like 'unused variable', 'unreferenced label' or 'suggest explicit braces'. Moreover, it should not compile if used incorrectly, and in that case the error message will be understandable. For instance :

    NAMED(loop1) for(int i = 0 ; i < 10; i++) {
        NAMED(loop2) for(int j = 0 ; j < i ; j++) {
            cout << i << "," << j << endl;
            if(j == 5) {
                BREAK(loop1);   // this one is okay, we exit the outer loop
        BREAK(loop2); // we're outside loop2, this is an error

The previous code will not compile, and the compiler error message for the second BREAK : '_YOU_CANNOT_USE_NAMED_BREAK_IF_YOU_ARE_OUTSIDE_loop2_` which is very explicit.


Before asking my question, I provide two examples to illustrate the (relative) usefulness of those constructs :

break an outer loop :

     NAMED(myloop) for(int i = 0 ; i < rows; i++) {
            if(some_condition) {

Exit a specific scope :

NAMED(myscope1) {
    cout<< "a";
        cout << "b";
            cout << "c";
            cout << "d";
        cout << "e";
    cout <<"f";

This code prints : abcf.

My question

Before defining what my question is, I must define what it isn't since I don't want to see my topic closed in 10 minutes.

It is not "Is it a good idea?", nor "What do you think?" or even "Is it useful?", since stackoverflow doesn't seem to be a discussion place. Anyway, I already know the answers : "Macro are evils", "Goto's are evil" & "Use lambdas instead".

Instead, my question is about technical correctness & robustness against programming errors. I want this construct to be as safe as possible.

  • Is it possible for an user to misuse it and still be able to compile ? I tried to fix the obvious problems of the original implementation, but C++ is very complex and maybe I missed something ?

  • Could it silently break some good looking code ? This is my main concern. Can it interfere with the other C++ features (exception handling, destructor calls, others conditionals statements, or anything else...) ?

My objective is to demonstrate that this construct is not intrinsically dangerous. I already know that it would be a very bad idea to use it in real code since others programmers may not clearly understand it, but is it safe-enough to be used in a personal project ?

EDIT : The boolean variable is now const (thanks to Jens Gustedt). I'll try to replace the ifs by fors later to check it can removes spurious warning when used like that :


EDIT2: As noticed by JensGustedt, variable declaration in an if statement is not allowed in C (C++ only). Another reason to replace it by a loop.

share|improve this question
This is very clever, but honestly I think you would be better off just using goto. –  Zack Jun 17 '12 at 14:55
Everyone knows goto. People who read this will probably sit down and try to figure out what the macros are doing, and then look at the code where they're used. This wouldn't be a great use of time when first reading your source code. –  chris Jun 17 '12 at 15:09
@Zack : The goal of this construct is to avoid using goto directly, and provide a safer syntax for exiting nested scopes. Here the label is automatically created to jump outside the scope, reducing the risk of error. –  Frédéric Terrazzoni Jun 17 '12 at 15:11
@chris : I totally agree with you, that's why I precised it is not aimed to be used in real code. I like this syntax and I want to use it in my personal project. Nobody else is supposed to read my code. I only want to be sure it's doesn't have a hidden design flaw that could break my code silently in some unusual situations (could be related to exception handling, destructor calls, etc...) –  Frédéric Terrazzoni Jun 17 '12 at 15:14
@FrédéricTerrazzoni, If it's only you, then I suppose it might be a bit better. I'm not sure if it will mess anything up, but it's too bad this wasn't implemented in C++ at all to be honest. I've found myself staring at that problem and having to do something about it more than once. –  chris Jun 17 '12 at 15:16

2 Answers 2

I really can't answer for c++ aspects, but since you also labeled it C ...

Usually using if/else constructs for such a thing is not so good of an idea, since you will always find a good-meaning C compiler that will find a warning in place for bizarre else matchings and things like that.

I usually use for constructs like that for P99. They avoid dangling else (or spurious warnings about it). Also for is the only place in C that you may place local variables the way you need them, they aren't allowed in if or while as they would be in C++.

On the "safety" side, you'd probably should declare the variable register bool const instead of just bool. So nobody could try to change it or even take its address to change it behind your back.

But for the particular purpose that you are using it I am not too much fond of for or goto either. What you are really doing is unwinding the stack. In C there is one construct to do that properly, namely setjmp/longjmp. In C++ it probably would be try/catch.

share|improve this answer
I labelled C & C++ since it doesn't rely on any C++ specific feature. Regarding the for vs if choice, I think this is a very good suggestion since I got some spurious warning writing if(condition) BREAK(label); else { }. You second suggestion of defining the variable register bool const is also interesting to prevent the malicious user to hijack it. Thank you. –  Frédéric Terrazzoni Jun 17 '12 at 15:39
I absolutely would not recommend exception semantics for scope exiting. Using try/catch for control flow is hideous and bad, simply because that's not what it is for. –  Xeo Jun 17 '12 at 15:40
His macros are defined without dangling elses, so the compilers should all be happy there. Both macros emit complete statements. –  Jesse Chisholm Jun 17 '12 at 15:47
@FrédéricTerrazzoni, yes it does rely on a specific C++ feature. Variable declarations inside the if clause is not possible in C, as I said. –  Jens Gustedt Jun 17 '12 at 16:14
Speaking personally, I would rather use the macros than setjmp() and longjmp(). –  Jonathan Leffler Jun 17 '12 at 16:21

I presume you have tested this, but ... isn't the bool variable you declare in NAMED(bn) still available later in the same block the if statement it is declared in exists? (: Your idiom won't work unless it is so. :)

I can see this being safe:

    NAMED(one) { ... }

The compiler will fuss on the BREAK(nb); line

But this still looks unsafe:

    NAMED(bn) { ... }

Unsafe in the sense that the compiler may still accept the variable as defined and not fuss. But it could form an infinite loop, thus silently breaking your program.


PS: It will not interfere with try..finally as the finally block is defined to be executed regardless of how you exit the try block. So as long as you aren't trying to avoid the finally block, you are OK.

P(PS)S: the only really weird interaction with other constructs I see is this:


And that is pathological! ;-D That will compile fine in DEBUG but get the compiler error in RELEASE.

share|improve this answer
BREAK requires the boolean variable to be defined in its scope. The NAMED macro creates a new scope to store it, so in this case it won't compile and the compiler will throw '_YOU_CANNOT_USE_NAMED_BREAK_IF_YOU_ARE_OUTSIDE_bn_' was not declared in this scope –  Frédéric Terrazzoni Jun 17 '12 at 15:46
Of course if the NAMED is only defined in DEBUG, it won't work. That said, I prefer a compilation error than a runtime crash / undefined behavior :) –  Frédéric Terrazzoni Jun 17 '12 at 15:53

Your Answer


