How to write a `for` loop over bool values (false and true)

C++For LoopBoolean

C++ Problem Overview


A question mostly for fun/curiosity: how to write a for loop in C++ that would iterate over two values of a bool (i.e. true and false), using only operations with bool (i.e. without conversions to other types)?

The background is that I wanted to check how many solutions exists for an equation like (A && B) || (!B && !C && !D) == true, and started to write something like for (bool A=false; ??? ; ++A) for (bool B=false; ...) etc but immediately got stuck by ??? - i.e. what would be the condition to continue the loop? Of course I rewrote it to use int, and I also know that a do ... while loop will work, but I got curious if it's ever possible to write such a for loop? And since SO does not seem to have an answer, I decided to ask :)


Update: note that an "obvious" variant for(bool A=false; !A; A=true) suggested in at least two now-removed answers will only run one iteration, because for the second one the condition !A becomes false and the loop ends.

After some pondering, I believe it's impossible to do it in C++03 without a second variable or a pointer based construct like suggested by Dietmar Kühl. The condition should be tested three times in a desired execution, so two values of a bool are simply not enough. And the do-while loop works because the first iteration is executed unconditionally, the condition is only checked twice and so a bool value can be used to select between continuing and exiting.

C++ Solutions


Solution 1 - C++

In C++11: for (bool b : { false, true }) { /* ... */ }


Here's a C++03 version:

for (bool a = true, b = false; b != a; a = a && b, b = !b) { /*...*/ }

(Use either a or b.)

Solution 2 - C++

When restricted to C++2003 you could use an approach roughly equivalent to the C++2011 approach;

{
  bool const bools[] = { false, true };
  for (bool const* it(bools); it != std::end(bools); ++it) {
      bool a(*it);
      use(a);
  }
}

Possibly packed up in a macro. You can also use

for (bool a: { false, true }) {
    use(a);
}

Solution 3 - C++

for (int a = 0; a <= 1; a++)
  doStuff(a ? true : false);

And forget about "no conversions to other types" restriction :) In the end of the day clarity is more important than artificial restrictions. Five years down the line you'll be reading your own code and wondering "what the heck was I thinking, is this some sort of an obfuscation contest?"

Solution 4 - C++

a = true;
do {
  use(a);
  a = !a;
} while (!a);

OK, so it's not a for loop, but I would argue it is more readable than any of the for loop suggestions (other than the C++11 approach, of course.)

Solution 5 - C++

One more for C++03:

for(bool a = false, b = true; b; a = !a, b = a)  

Use b.

Solution 6 - C++

This answer addresses the "impossible" C++03, single-variable only solution

First, let us confirm that no deterministic arithmetic expression relying only on a single input variable can be true for both inputs true,false but then not for a third value that must be one of true or false.

However, we can "cheat". Though, I'd implore you to prove I'm actually cheating.

#include <iostream>

using namespace std;

int main() {
    for (bool b = false; *((char*)&b) != 2; *((char*)&b) += 1) {
        cout << "bool " << b << endl;
    }
}

This certainly seems like undefined behavior. C++03 is a bit unclear about it. However, sizeof must always be at least 1 (with a non-standard exception for 0-length var-len arrays). Moreover, since we're guaranteed each char is at least 8 bits, we can use the second one for our counter.

Indeed, to do this we need to either skirt determinism (can't without giving up the guarantee we iterate over false, true exactly once) or our constraining type system.

Solution 7 - C++

This one works, too:

for (bool a = false, b = false; a == b; b = !b, a = a || b) { }

(sort of inverted solution than @KerrekSB's)

Solution 8 - C++

I know you asked for a solution without conversion to other type, but I suppose you mean "without conversion to unappropriated other type". Here is an answer offering an object replacing bool in this specific case.

struct IterableBool
{
  bool b;
  bool out_of_scope;
  IterableBool() : b(false), out_of_scope(false) {}
  IterableBool(bool b_) : b(b_), out_of_scope(false) {}
  IterableBool(IterableBool ib) : b(ib.b), out_of_scope(ib.out_of_scope) {}
  operator bool () { return this->b; }
  bool in_scope() const { return !this->out_of_scope; }
  IterableBool& operator ++ ()
  {                    
    this->out_of_scope = this->b;
    this->b = true;
    return *this;
  }
  IterableBool operator ++ (int)
  {
    IterableBool copy = *this;
    ++(*this);
    return copy;
  }
  IterableBool& operator -- ()
  {
    this->out_of_scope = !this->b;
    this->b = false;
    return *this;
  }
  IterableBool operator -- (int)
  {
    IterableBool copy = *this;
    --(*this);
    return copy;
  }
};

// Usage :
for(IterableBool ib = false;  ib.in_scope(); ++ib)
  do_stuff((bool)ib);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexey KukanovView Question on Stackoverflow
Solution 1 - C++Kerrek SBView Answer on Stackoverflow
Solution 2 - C++Dietmar KühlView Answer on Stackoverflow
Solution 3 - C++Andrei PokrovskyView Answer on Stackoverflow
Solution 4 - C++mdkView Answer on Stackoverflow
Solution 5 - C++AotiumView Answer on Stackoverflow
Solution 6 - C++VF1View Answer on Stackoverflow
Solution 7 - C++jrokView Answer on Stackoverflow
Solution 8 - C++CaduchonView Answer on Stackoverflow