2012-01-10 68 views
40

,一个最好玩/好奇的问题:如何编写C++,将遍历的bool(即truefalse)两个值一for循环,只使用bool的操作(即不转换为其他类型)?如何写在布尔值的`for`环路(假,真)

背景是,我要检查有多少解决方案,像(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和循环结束。

经过一番琢磨之后,我认为这是不可能做到这一点在C++ 03没有迪特马尔库尔提出第二个变量或基于指针结构等。该条件应该在期望的执行中测试三次,所以bool的两个值是不够的。而do-while循环工作,因为第一次迭代无条件地执行,条件只有两次检查等一个布尔值可用于持续和退出之间进行选择。

+2

令人惊讶的是,错误的答案被迅速删除! – 2012-01-10 14:57:39

+1

是的,当他们这样做时你不讨厌它吗?我觉得这是一个很好的问题。我upvoted。 – 2012-01-10 15:01:54

+0

因为这个网站不是为了好玩/好奇。真正的问题! PS不,这不是我,我也很好奇。 – 2012-01-10 15:02:19

回答

48

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


这里是一个C++ 03版:(二者必选其一ab

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

+1

这是初始化程序列表的一个有趣的版本。 – Xeo 2012-01-10 15:30:46

1

这一个作品,太:

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

(排序倒液比@ KerrekSB的)

6

当仅限于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); 
} 
+0

我想你可能会将该数组打包到for循环的声明部分。但不知道。 – Xeo 2012-01-10 15:29:43

+0

你的魔法2与整个想法相矛盾。 – Wolf 2017-11-15 09:18:08

+1

@Wolf:回复是2012年写的。我想,以前我并没有假设C++ 11一般都可用(尽管我发现了实现'std :: end()'-1998所需的功能。 – 2017-11-15 14:56:11

2

一个多用于C++ 03:

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

使用b。

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

忘记“没有转换为其他类型”限制:)在一天结束时,清晰度比人工限制更重要。五年下来,你会阅读自己的代码,不知道行“你到底是怎么想,这是某种形式的混淆比赛的?“

+0

如果您使用'char' /'uint8_t'而不是'int',那么他们很可能会编译成相同的基础数据类型并给你零成本的铸造。 – 2017-03-13 15:07:59

+0

@ SlippD.Thompson它取决于'doStuff'' int是否有效。 – Wolf 2017-11-15 09:20:46

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

OK,所以它不是为环路,但我认为它比任何的for循环的建议更具有可读性(除C++ 11的方式等,当然)。

+0

按照预期在循环内部继续工作:a = false;做{...} while(a =!a);'。变量/常量中的初始值:'a = init;做{...} while(init!=(a =!a));' – adf88 2017-05-07 06:31:03

2

此答案解决了“不可能的” C++ 03,单变量只溶液

首先,让我们确认没有确定性的算术表达式只在一个单一的输入变量可以依赖两个输入true,false但随后不是真的第三个值必须是truefalse之一。

但是,我们可以“欺骗”。虽然,我会恳求你证明我实际上在作弊。

#include <iostream> 

using namespace std; 

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

这当然似乎喜欢不确定的行为。 C++ 03有点unclear about it。但是,sizeof必须至少为1(对于0长度的var-len数组,非标准例外)。而且,由于我们保证每个字符至少有8位,所以我们可以使用第二个字符作为我们的计数器。事实上,要做到这一点,我们需要裙摆决定论(不能放弃保证我们只重复一次false, true)或我们的约束类型系统。

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); 
相关问题