83

Python has an interesting for statement which lets you specify an else clause.

In a construct like this one:

for i in foo:
  if bar(i):
    break
else:
  baz()

the else clause is executed after the for, but only if the for terminates normally (not by a break).

I wondered if there was an equivalent in C++? Can I use for ... else?

Aya
  • 39,884
  • 6
  • 55
  • 55
Delgan
  • 18,571
  • 11
  • 90
  • 141
  • 4
    It's an interesting idea that comes up every now and then. Out of curiosity, how often is such a construction used in real code? – Kerrek SB Jul 11 '14 at 09:05
  • 5
    @KerrekSB This is the real question. When I started learning Python I kind of found this to be trivial and confusing to beginners at best; I couldn't find any pressing requirement for this construct. – legends2k Jul 11 '14 at 09:08
  • I know it's a real question, but it's not real code -it's just too and bar. I'm wondering how often real algorithms need an explicit extra branch that only applies when the loop completes. I can't think of useful examples right now. – Kerrek SB Jul 11 '14 at 09:13
  • 1
    @KerrekSB implementing `find()` is a classic example where this conctruct is used. – m.wasowski Jul 11 '14 at 09:21
  • 2
    @m.wasowski: really? Usually the standard early return works just fine for find-like algorithms, with no need for a separate "loop complete" block. – Kerrek SB Jul 11 '14 at 17:53
  • @Kerrek: Usually the early return really is a `return`, not a `break`, and then it does skip the code immediately following the loop. – Ben Voigt Jul 12 '14 at 19:09
  • 1
    I do like this construction, and I made a search to see If I could find some use cases of it in my code to answer @KerrekSB , but i need to post it as a answer because comments are not enough – agomcas Dec 16 '15 at 06:37
  • 6
    @agomcas: I have since been convinced that this construction is useful. The reasoning is this: All three of `if (c)`, `while (c)` and `for (...; c; ...)` evaluate `c`, but at present only the first one lets you access the result of this expression. The other two are throwing away this information, which violates the principle that you should not throw away results that were obtained as part of a computation. – Kerrek SB Dec 16 '15 at 09:54
  • 1
    However, I would have liked it much more if the keywords would have been other than 'else'. Something like 'nobreak' or even 'felse' and 'welse' that makes the intention stand out more than the plain else. Every time I use it I feel the need to add a comment #for else in that line, just in case. – agomcas Dec 18 '15 at 05:35
  • 1
    @agomcas: `not break` *statement-block* has the benefit of using existing keywords, for better backwards compatibility (and being strongly indicative of the conditions under which it runs). In C++ the use of `else` for this would conflict with existing code a la `if (...) for (...) ...; else ...`. – Tony Delroy Dec 18 '15 at 09:02
  • 1
    Most of the time, when I encounter this need, I extract a method and replace `break` by `return`. – etham Sep 24 '22 at 06:05

14 Answers14

42

If doesn't mind using goto also can be done in following way. This one saves from extra if check and higher scope variable declaration.

for(int i = 0; i < foo; i++)
     if(bar(i))
         goto m_label;
baz();

m_label:
...
ifyalciner
  • 1,190
  • 1
  • 10
  • 22
  • 3
    @MatthiasB As far as I understand question is not about what to use, instead it is about the possible implementations in C++. – ifyalciner Jul 11 '14 at 09:51
  • 6
    @MatthiasB And also I don't think that 'goto' is outdated. Because there are still fields where you need to omit extra 'if' checks and declarations for performance and memory considerations, while still programming in C++. – ifyalciner Jul 11 '14 at 10:01
  • You may add your own exception, else you badly catch exception from `bar(i)` and `baz()` – Jarod42 Jul 11 '14 at 11:26
  • @Jarod42 you are right. Custom exception would be better. – ifyalciner Jul 11 '14 at 12:20
  • @MatthiasB I think [this](https://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array) will be a good example. Actual impact of the thread actually about emptying pipeline because of the false prediction in the case. But still a branch can effect terribly. Especially if you are repeating many times which i don't see reason the neglect many repetitions because domain is absent. Also I use C++ in embedded systems. You are right that it is not a good practice but still i believe is a good exception. – ifyalciner Jul 11 '14 at 12:28
  • 1
    @Faruxx I'm afraid you'll have to elaborate. There is not a single mention of "goto" in that question, and the subject matter (branch prediction) doesn't lend itself to any obvious examples. The issue is an unpredictable jump in the machine code, a `goto` also produces jump instructions and does not alter predictability. –  Jul 11 '14 at 13:46
  • @delnan Sorry I couldn't be clear. My point was that by using `goto` you can eliminate a branch. And in the link if you check the answers will see that one solution to branch prediction is removing the branch altogether. But still I see no more necessity of the arguing on the matter. Thanks for all responses. – ifyalciner Jul 11 '14 at 13:52
  • @Faruxx A `goto` **is** a branch (possibly an unconditional one). The only instance of [removing branches](http://stackoverflow.com/a/17828251/395760) code I could find in the answers doesn't use `goto`. If you want to argue that `goto` allows replacing conditional branches with unconditional ones, please give an example because so far it sounds like cargo cult. –  Jul 11 '14 at 14:48
  • @delnan in the most voted answer; [here](http://stackoverflow.com/a/11227902/2534369) : `int t = (data[c] - 128) >> 31; sum += ~t & data[c];`. Of course `goto` is a branch such as `break`. I have removed second branch which is a conditional one that you can see in other answers. – ifyalciner Jul 12 '14 at 08:14
  • @Faruxx Okay, missed that one, but it doesn't need or use `goto` either. I'm aware of branch prediction and its effects and no not dispute them. What I'm asking is how `goto` helps avoid branch mispredictions. –  Jul 12 '14 at 09:00
  • @delnan No no! I never meant that. It helps only to remove branch removal where theoretically you are removing branch correct or mis prediction. The reason i have given that example is this code block may repeat many times, one more `if` check will increase the chance of branch mis-prediction (as well as correct prediction). In some cases where code optimization is important `goto` is still a good practice for experienced ones. @MatthiasB is right where you are coding for an user application in big project with many people that understandably of code is more important than optimization. – ifyalciner Jul 12 '14 at 09:13
  • You don't need a semicolon after the label. The context implies there are operators after this code (otherwise one could just use an early return). – Андрей Беньковский Dec 10 '15 at 19:14
  • 5
    The goto part isn't that bad. That's what I'd use in this situation. I think it is actually more readable than the flag-based solution. – Андрей Беньковский Dec 10 '15 at 19:20
  • @АндрейБеньковский Thanks for suggestions and mentioning. – ifyalciner Dec 15 '15 at 14:33
  • 4
    If we consider language equivalency, then this is the only valid answer. Python does not have gotos, while C++ has, and all other examples, such as using return, a temporary variable and break, or exceptions can be done with Python. Plus, this case (for else) as well as breaking out of a nested loop are probably the two only cases of valid applications of goto in C++. – 0kcats Dec 15 '15 at 14:49
  • 5
    goto is well defined and often the most comprehensible (i.e. best maintainable) solution for complex loop handling. This solution has my vote (I would have given a similar one). – kamikaze Dec 15 '15 at 16:02
  • I think using goto is antipattern nowadays, but if you do it on this micro place I think you are okay, but I think this should be last thing to consider to use. – Matej Kolec'ko Oct 15 '19 at 09:03
  • @MatthiasB Can you explain which construct he uses that you think is outdated? – 12431234123412341234123 May 17 '21 at 16:32
  • @MatthiasB This answer is a prime example why `goto` isn't outdated in C. – 12431234123412341234123 May 19 '21 at 10:46
39

A simpler way to express your actual logic is with std::none_of:

if (std::none_of(std::begin(foo), std::end(foo), bar))
    baz();

If the range proposal for C++17 gets accepted, hopefully this will simplify to:

if (std::none_of(foo, bar)) baz();
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • 11
    Not completely equivalent. For example, it does not allow modification of the elements of the container by the "bar". Not to mention, that it made me (a C++ dev) go look it up in the help, while the the original OP python sample I had no problem understanding immediately. The stl turns into a mud pile. – 0kcats Dec 16 '15 at 03:48
  • 2
    I was referring to the help page here: http://www.cplusplus.com/reference/algorithm/none_of/ or here http://en.cppreference.com/w/cpp/algorithm/all_any_none_of. Both say that the predicate shall not modify the argument. – 0kcats Dec 16 '15 at 06:06
  • @0kcats: hmmm... 25.1/8 does say *"The function object pred shall not apply any non-constant function through the dereferenced iterator."*, so you're right. Interesting! Related discussion [here](http://www.drdobbs.com/effective-standard-c-library-unary-predi/184403777). Cheers – Tony Delroy Dec 16 '15 at 06:37
15

This is my rough implementation in C++:

bool other = true;
for (int i = 0; i > foo; i++) {
     if (bar[i] == 7) {
          other = false;
          break;
     }
} if(other)
     baz();
Easton
  • 225
  • 1
  • 5
15

Yes you can achieve the same effect by:

auto it = std::begin(foo);
for (; it != std::end(foo); ++it)
     if(bar(*it))
         break;
if(it == std::end(foo))
    baz();
haccks
  • 104,019
  • 25
  • 176
  • 264
  • 2
    Note that this counts up from 0 to foo while the Python loop goes through the elements of the iterable foo. Probably easy to adjust though (compare to `end()`). –  Jul 11 '14 at 09:02
  • 3
    No. The Python loop doesn't count at all. `i` probably never is an integer. It's more like C++11 `for (auto i : foo)`. –  Jul 11 '14 at 09:04
  • 3
    `for(auto it = begin(something); it != end(something); ++i)` ... if (it == end(something))`... Also please remember, that everytime you do postfix incrementation unecessary, a kitten dies. – m.wasowski Jul 11 '14 at 09:07
  • @m.wasowski could you please explain why `i++` would be so bad in a forloop? It's got *exactly* the same functionality as `++i` there. I personally think `i++` looks better, because it's got the part that changes the variable *after* the variable name itself, just like where `+=1` comes after `i` in the normal `i+=1`, etc. In cases where it doesn't matter to the outcome of the code, I *always* use `i++`. – Joeytje50 Nov 29 '14 at 00:22
  • 1
    @Joeytje50 `i++` can be significantly slower, as it involves creating a new object; it is a bad habit to use it and you won't find it in decent code in place where `++i` can be used instead. Personally, it forces me unecessarilly to slow down and think if there is was a reason to use it, or is it just sloppy code. Even if for a second, it might be annoying. – m.wasowski Nov 30 '14 at 22:17
  • @m.wasowski [this guy's tests say otherwise](http://stackoverflow.com/a/24887/1256925). I get why `i++` could be slower in some situations, but in a forloop it makes no difference if you've got a modern enough compiler (which is what I'm taking from that SO link), so I would still prefer `i++` because of those things I said. So, to fix your original statement: "Everytime you do postfix incrementation unnecessarily, your compiler turns it into exactly the same as prefix incrementation." – Joeytje50 Nov 30 '14 at 22:24
  • 1
    @Joeytje50 mind that this is answer for a different programming language. For example, iterators are not primitive types like `int`. Also see comments below, you will find all the reasons why `++i` should be used as default. And IMHO, for sake of consistency, the same should be used for primitive types, like `int`. – m.wasowski Nov 30 '14 at 22:34
14

You could use a lambda function for this:

[&](){
  for (auto i : foo) {
    if (bar(i)) {
      // early return, to skip the "else:" section.
      return;
    }
  }
  // foo is exhausted, with no item satisfying bar(). i.e., "else:"
  baz();
}();

This should behave exactly like Python's "for..else", and it has some advantages over the other solutions:

  • It's a true drop-in replacement for "for..else": the "for" section can have side effects (unlike none_of, whose predicate must not modify its argument), and it has access to the outer scope.
  • It's more readable than defining a special macro.
  • It doesn't require any special flag variables.

But... I'd use the clunky flag variable, myself.

Noah Black
  • 140
  • 2
  • 5
4

I am not aware of an elegant way to accomplish this in C/C++ (not involving a flag variable). The suggested other options are much more horrible than that...

To answer @Kerrek SB about real life usages, I found a few in my code (simplified snippets)

Example 1: typical find/fail

for item in elements:
    if condition(item):
        do_stuff(item)
        break
else: #for else
    raise Exception("No valid item in elements")

Example 2: limited number of attempts

for retrynum in range(max_retries):
    try:
        attempt_operation()
    except SomeException:
        continue
    else:
        break
else: #for else
    raise Exception("Operation failed {} times".format(max_retries))
agomcas
  • 695
  • 5
  • 12
  • The first example can be replaced with an if statement using python's built-ins `any` and `map` or an iterator comprehension. – Андрей Беньковский Dec 17 '15 at 14:01
  • @agomcas: this is very interesting, as is the contrast with equivalent C++, e.g.: `for (int retrynum = 0; ; ++retrynum) { try { attempt_operation(); } catch (const SomeException&) { if (retrynum == max_retries) throw ...; } }`. Not sure which I prefer. – Tony Delroy Dec 18 '15 at 05:04
  • @АндрейБеньковский but I believe with the any() construction there is not way to recover which element fulfilled the condition. In the for...else case you have it stored in item and may do something else with it. – agomcas Dec 18 '15 at 05:25
  • @agomcas I continued my experiments. [link](http://melpon.org/wandbox/permlink/2XKM89VlAwjY90fa). I'm not sure which of two solutions is more readable. – Андрей Беньковский Dec 18 '15 at 06:17
  • @agomcas A bit more improved version: http://melpon.org/wandbox/permlink/xiQBiPYY9zBV0ceY – Андрей Беньковский Dec 18 '15 at 06:25
  • @АндрейБеньковский For me, readability of the for... else is better by far. The other option involves creation of a separate sentinel object + using the generator returned from filter + using next with a default return (first time I ever encountered this usage BTW). It goes from a construction that you can explain in an introduction to programming right just after 'if...else' and 'for' to a construction that needs quite some knowledge of python (plus I bet is more expensive in resources), just to match the same amount of lines. Not really a contender? – agomcas Dec 18 '15 at 07:32
  • @agmos: *"with the `any()` construction there is not way to recover which element fulfilled the condition"* - that's part of the self-documenting beauty of it - the code reader knows up front that it doesn't matter which element matches whenever `any` is used, while `find_if` implies it may matter. Good programmers will pick accordingly. – Tony Delroy Dec 18 '15 at 08:48
3

Something like:

auto it = foo.begin(), end = foo.end();
while ( it != end && ! bar( *it ) ) {
    ++ it;
}
if ( it != foo.end() ) {
    baz();
}

should do the trick, and it avoids the unstructured break.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 1
    The `break` is fine IMHO, and in any case that change is completely orthogonal to the actual meat (`it != foo.end()`). –  Jul 11 '14 at 09:09
  • @BenVoigt Good point. That's what comes of typing too quickly. Should be a `while`; I'll fix it. – James Kanze Jul 14 '14 at 07:52
2

There is no such language construct in C++, but, thanks to the "magic" of the preprocessor, you can make one for yourself. For example, something like this (C++11):

#include <vector>
#include <iostream>
using namespace std;

#define FOR_EACH(e, c, b) auto e = c.begin(); for (; e != c.end(); ++e) {b} if (e == c.end()) {}

int main()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);

    FOR_EACH(x, v, {
        if (*x == 2) {
            break;
        }        
        cout << "x = " << *x << " ";
    })
    else {
        cout << "else";
    }

    return 0;
}

This should output x = 1 else.

If you change if (*x == 2) { to if (*x == 3) {, the output should be x = 1 x = 2.

If you don't like the fact that a variable is added in the current scope, you can change it slightly:

#define FOR_EACH(e, c, b, otherwise) {auto e = c.begin(); for (; e != c.end(); ++e) {b} if (e == c.end()) {} otherwise }

then use would be:

FOR_EACH(x, v, {
    if (*x == 2) {
        break;
    }        
    cout << "x = " << *x << " ";
},
else {
    cout << "else";
})

It's not perfect, of course, but, if used with care, will save you some amount of typing and, if used a lot, would become a part of the project's "vocabulary".

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
srdjan.veljkovic
  • 2,468
  • 16
  • 24
  • 4
    Sacrificing readability to save 5 seconds of typing is usually a very bad idea. – Андрей Беньковский Dec 11 '15 at 17:16
  • Well, readability is subjective, while typing isn't. It's a trade-off, like everything else. I'm not advocating its use, just showing how you can achieve a "for each...else" in C++ without goto (which has its own problems). – srdjan.veljkovic Dec 11 '15 at 17:56
  • 3
    A goto pattern here is much, much better than declaring a macro. – 0kcats Dec 15 '15 at 14:43
  • I'm not sure how I feel about the macro leaving behind a new variable in my scope. In your example an iterator `x` will be left behind after the else statement. There isn't a nice way to get around this one... – nonsensickle Feb 01 '17 at 08:49
  • I added an example of a way to avoid bringing a new variable into current scope. I'm not saying it's nice, but, it works. :) – srdjan.veljkovic Feb 01 '17 at 21:14
2

It's not only possible in C++, it's possible in C. I'll stick with C++ to make the code comprehensible though:

for (i=foo.first(); i != NULL || (baz(),0); i = i.next())
{
    if bar(i):
        break;
}

I doubt I'd let that through a code review, but it works and it's efficient. To my mind it's also clearer than some of the other suggestions.

0

There probably isn't a single solution that fits best all problems. In my case a flag variable and a range-based for loop with an auto specifier worked best. Here's an equivalent of the code in question:

bool none = true;
for (auto i : foo) {
  if (bar(i)) {
    none = false;
    break;
  }
}
if (none) baz();

It is less typing than using iterators. Especially, if you use the for loop to initialize a variable, you may use that instead of the boolean flag.

Thanks to auto typing it is better than std::none_of, if you want to inline the condition rather than call bar() (and if you are not using C++14).

I had a situation where both conditions occurred, the code looked something like this:

for (auto l1 : leaves) {
  for (auto x : vertices) {
    int l2 = -1, y;
    for (auto e : support_edges[x]) {
      if (e.first != l1 && e.second != l1 && e.second != x) {
        std::tie(l2, y) = e;
        break;
      }
    }
    if (l2 == -1) continue;

    // Do stuff using vertices l1, l2, x and y
  }
}

No need for iterators here, because v indicates whether break occurred.

Using std::none_of would require specifying the type of support_edges[x] elements explicitly in arguments of a lambda expression.

Community
  • 1
  • 1
arekolek
  • 9,128
  • 3
  • 58
  • 79
  • Why would it require specifying the type? – Yam Marcovic Feb 07 '16 at 16:17
  • @YamMarcovic Admittedly, I wasn't aware you can use [auto specifier in lambdas](http://ideone.com/laenSZ). But [it works only in C++14](http://stackoverflow.com/questions/30071453/how-to-use-lambda-auto-parameters-in-c11) and I was using C++11. – arekolek Feb 07 '16 at 18:08
0

Direct answer: no, you probably can't, or it is compiler-based, at best. BUT here's a hack of a macro that kind of works!

A few notes:

I usually program with Qt, so I'm used to having a foreach loop, and never have to deal with iterators directly.

I tested this with Qt's compiler (v 5.4.2) but it should work. This is gross for several reasons, but generally does what you'd want. I don't condone coding like this, but there's no reason it shouldn't work as long as you're careful with the syntax.

#include <iostream>
#include <vector>

#define for_else(x, y) __broke__ = false; for(x){y} if (__broke__) {}
#define __break__ __broke__ = true; break

bool __broke__;  // A global... wah wah.

class Bacon {
  public:
    Bacon(bool eggs);

    inline bool Eggs() {return eggs_;}

  private:
    bool eggs_;
};

Bacon::Bacon(bool eggs) {
  eggs_ = eggs;
}

bool bar(Bacon *bacon) {
  return bacon->Eggs();
}

void baz() {
  std::cout << "called baz\n";
}

int main()
{
  std::vector<Bacon *>bacons;

  bacons.push_back(new Bacon(false));
  bacons.push_back(new Bacon(false));
  bacons.push_back(new Bacon(false));

  for_else (uint i = 0; i < bacons.size(); i++,
      std::cout << bacons.at(i)->Eggs();
      if (bar(bacons.at(i))) {
        __break__;
      }
  ) else {
    baz();
  }

  bacons.push_back(new Bacon(true));
  bacons.push_back(new Bacon(false));

  for_else (uint i = 0; i < bacons.size(); i++,
      std::cout << bacons.at(i)->Eggs();
      if (bar(bacons.at(i))) {
        __break__;
      }
  ) else {
    baz();
  }

  return EXIT_SUCCESS;
}
0

You can use for-else almost like in Python by defining two macros:

#define BREAK {CONTINUETOELSE = false; break;}
#define FORWITHELSE(x, y) {bool CONTINUETOELSE = true; x if(!CONTINUETOELSE){} y}

Now you put the for and the else inside the FORWITHELSE macro separated by a comma and use BREAK instead of break. Here is an example:

FORWITHELSE(
    for(int i = 0; i < foo; i++){
        if(bar(i)){
            BREAK;
        }
    },
    else{
        baz();
    }
)

There are two things you need to remember: to put a comma before the else and to use BREAK instead of break.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
0

I came here because I had the same question, in C though. The best thing I came out with is

bool notTerminated = true;
for (int i = 0; i < 50 || (notTerminated = false); i++)
    if (bar(i))
        break;
if (! notTerminated)
    baz();

Explanation: the (notTerminated = false) is an assignment that will always return the false value, it will never affect the condition and will be evaluated iif the condition if true.

-1

I would accomplish this with a simple helper variable:

#include <stdio.h>
#include <stdbool.h>

int main()

{
    bool b;
    printf("Numbers which are multiples of 7:\n");

    for (int i=8; b=(i<12); i++)
    {
        if (i%7==0)
        {
            printf("%d", i);
            break;
        }
    }
    if (!b)
    {
        printf("no numbers found\n");
    }
    return 0;
}

This way, you need to implement the condition (in the above examplei<12) only at one place.

MiCo
  • 399
  • 2
  • 6