2

Let's consider:

switch(x)
{
case something:
    {
        for(something_else : some_container)
        {
             if(a_condition)
             {
             // BREAK OUT OF THE SWITCH
             }
        }
        some_statements();
        break;
        }
}

How can I escape in the most elegant way from the loop which is inside a switch statement since I do not want to run some_statements();.

Certainly a well placed goto would nicely solve this problem, but the solution can be considered anything but elegant:

switch(x)
{
case something:
    {
        for(something_else : some_container)
        {
             if(a_condition)
             {
                  goto escape_route;
             }
        }
        some_statements();
        break;
        }
}
escape_route:
// Hurrah, freedom 

And also a flag would solve this problem:

switch(x)
{
case something:
    {
        bool flag = true;
        for(something_else : some_container)
        {
             if(a_condition)
             {
                  flag = false;
                  break;
             }
        }
        if(flag)
        {
            some_statements();
        }
        break;
        }
}

But let's just say, that I am looking for other solutions for this problem for the challenge's sake (Please note: There are more statements after the switch, returning is not an option).

Any ideas?

Ferenc Deak
  • 34,348
  • 17
  • 99
  • 167

4 Answers4

4

In general this is one of the few cases, where using gotos is often considered ok. However, since c++11 I prefer to use an immediately invoked lambda and a return statement:

[&]{
    switch(x)
    {
    case something:
        {
            for(something_else : some_container)
            {
                if(a_condition)
                {
                    return ;
                }
             }
             some_statements();
             break;
         }
     }
}(); //<- directly invokes the lambda

And once you have this, think if you might want to put the whole block into a separate named function.

Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
MikeMB
  • 20,029
  • 9
  • 57
  • 102
1

The goto version is ok but a better alternative might be to use a function and return from it upon an exceptional condition:

status_t func (void)
{
  status_t status = default_value;

  switch(x)
  {
    case something:
    {
      for(something_else : some_container)
      {
        if(a_condition)
        {
          return status;
        }
      }
      some_statements();
      break;
    }
  }

  return status;
}

The advantage here is that it allows you to use a status variable (for error codes etc).

Another alternative is exception handling.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

That goto looks okay. Don't overthink it -- you'll only make it more tangled.

That's for the general case, though. Your specific use looks like it can be folded into a nice call to an <algorithm>.

switch(x)
{
case something:
    {
        if(std::any_of(
            begin(some_container),
            end(some_container),
            [](auto &&e) { return a_condition(e); }
        ))
            break;

        some_statements();
        break;
    }
}

Notice that this calls a function which does the early returning, and immediately breaks out if it returned true.
Yes, you can mimick this pattern with your own function/lambda in place of std::any_of.
No, it's not a good idea if your function does not make sense on its own like std::any_of does.

Quentin
  • 62,093
  • 7
  • 131
  • 191
0

I would probably split the function into sub functions, removing your need of break inside the loop, something like:

void foo(/*...*/)
{
    for (auto something_else : some_container) {
         if (a_condition) {
             return;
         }
    }
    some_statements();
}

And then

switch (x)
{
    case something:  { foo (/*...*/); break; }
    case something2: { foo2(/*...*/); break; }
    case something3: { foo3(/*...*/); break; }
    // ...
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302