一个主要是为了好玩/好奇的问题:如何在C ++中编写一个for
循环来迭代bool
的两个值(即true
和false
) ,仅使用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值可用于在继续和退出之间进行选择。
答案 0 :(得分:55)
在C ++ 11中:for (bool b : { false, true }) { /* ... */ }
这是一个C ++ 03版本:
for (bool a = true, b = false; b != a; a = a && b, b = !b) { /*...*/ }
(使用a
或b
。)
答案 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);