如何在bool值上写一个`for`循环(false和true)

时间:2012-01-10 14:48:54

标签: c++ for-loop boolean

一个主要是为了好玩/好奇的问题:如何在C ++中编写一个for循环来迭代bool的两个值(即truefalse) ,仅使用bool的操作(即没有转换为其他类型)?

背景是我想检查像(A && B) || (!B && !C && !D) == true这样的等式有多少解决方案,然后开始写for (bool A=false; ??? ; ++A) for (bool B=false; ...)之类的东西,但立即被???卡住了 - 即什么是继续循环的条件?当然我重新编写它以使用int,我也知道do ... while循环可以工作,但我很好奇是否有可能编写这样的for循环?由于SO似乎没有答案,我决定问:)


更新:请注意,至少有两个现在删除的答案中建议的“明显”变体for(bool A=false; !A; A=true)只会运行一次迭代,因为对于第二次迭代,条件!A变为false并且循环结束。

经过一番思考,我相信如果没有第二个变量或者像DietmarKühl建议的基于指针的构造,在C ++ 03中做这件事是不可能的。条件应该在期望的执行中测试三次,因此bool的两个值是不够的。 do-while循环有效,因为第一次迭代是无条件执行的,条件只检查两次,因此bool值可用于在继续和退出之间进行选择。

8 个答案:

答案 0 :(得分:55)

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


这是一个C ++ 03版本:

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

(使用ab。)

答案 1 :(得分:7)

当限于C ++ 2003时,您可以使用大致相当于C ++ 2011方法的方法;

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

可能打包在宏中。您也可以使用

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

答案 2 :(得分:5)

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

忘记“没有转换到其他类型”限制:)在一天结束时,清晰度比人为限制更重要。五年后,你将会阅读自己的代码并想知道“我在想什么,这是某种混淆竞赛吗?”

答案 3 :(得分:4)

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

好的,所以它不是 for 循环,但我认为它比任何for循环建议更可读(当然,除了C ++ 11方法之外)。

答案 4 :(得分:2)

C ++ 03还有一个:

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

使用b。

答案 5 :(得分:2)

这个答案解决了&#34;不可能的问题。 C ++ 03,单变量解决方案

首先,让我们确认,对于两个输入true,false,不依赖于单个输入变量的确定性算术表达式都是真的,但是对于必须是true或{之一的第三个值,则不是{1}}。

然而,我们可以&#34;欺骗&#34;。虽然,我恳请你证明我实际上是在作弊。

false

这肯定似乎就像未定义的行为一样。 C ++ 03有点unclear about it。但是,#include <iostream> using namespace std; int main() { for (bool b = false; *((char*)&b) != 2; *((char*)&b) += 1) { cout << "bool " << b << endl; } } 必须始终至少为1(对于0长度的var-len数组,存在非标准异常)。此外,由于我们保证每个字符串至少为8位,我们可以将第二个字符用于我们的计数器。

事实上,要做到这一点,我们要么要么决定主义(不能放弃我们在sizeof完全迭代一次的保证)或我们的约束类型系统。

答案 6 :(得分:1)

这个也适用:

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

(比@ KerrekSB的反转解决方案)

答案 7 :(得分:0)

我知道你要求一个没有转换为其他类型的解决方案,但我想你的意思是“没有转换为未被占用的其他类型”。这是一个答案,在这个特定情况下提供一个替换bool的对象。

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);