More C++ Idioms/Named Loop

Named Loop

edit

Intent

edit

To partially simulate the labeled loop feature found in other languages.

Also Known As

edit

Labeled loop

Motivation

edit

Some languages, such as Java and Perl, support labeled looping constructs. In these languages, break and continue keywords can optionally specify a previously-defined loop label to control the flow of the program. A labeled break brings the control-flow out of the specified loop and similarly, a labeled continue starts with the next iteration. Labels allow breaking and continuing not just the innermost loop, but any outer loop that is labeled. Labeled break and continue can improve the readability and flexibility of complex code which uses nested loops. Named loop idiom in C++ provides partial support for this feature.

Solution and Sample Code

edit

The named loop idiom is implemented using gotos. Macros are used to hide the explicit use of gotos, which is often frowned upon. Only labeled break statements can be simulated using the following two parameterized macros.

#define named(blockname) goto blockname; \
                         blockname##_skip: if (0) \
                         blockname:

#define break(blockname) goto blockname##_skip

The named(X) macro defines two goto labels X and X_skip. The break macro is a simple goto to the X_skip label. An example follows.

struct test
{
  std::string str;
  test (std::string s) : str(s) { 
    std::cout << "test::test()::" << str << "\n"; 
  }
  ~test () { 
    std::cout << "~test::" << str << "\n"; 
  }
};

int main(void)
{
  named (outer) 
  for (int i = 0; i < 10; i++)
  {
    test t1("t1");
    int j = 0;
    named(inner)
    for (test t2("t2"); j < 5; j++)
    {
      test t3("t3");
      if (j == 1) break(outer);
      if (j == 3) break(inner);
      test t4("t4");
    }
    std::cout << "after inner\n";
  }
  return 0;
}

The gotos do not interfere with the proper construction and destruction of objects as confirmed by the output of the above program.

test::test()::t1

test::test()::t2

test::test()::t3

test::test()::t4

~test::t4

~test::t3

test::test()::t3

~test::t3

~test::t2

~test::t1

Known Uses

edit
edit

References

edit