web-dev-qa-db-ja.com

bool値(falseおよびtrue)に対して「for」ループを作成する方法

主に楽しみ/好奇心に関する質問:C++でforの2つの値(つまりbooltrue)を反復するfalseループを作成する方法)、boolを使用した操作のみを使用(つまり、他の型への変換なし)?

背景は、_(A && B) || (!B && !C && !D) == true_のような方程式の解がいくつ存在するかを確認したいと思っていて、for (bool A=false; ??? ; ++A) for (bool B=false; ...)などのようなものを書き始めましたが、すぐに_???_に行き詰まりました。ループを続けるための条件ですか?もちろん、intを使用するように書き直しました。また、_do ... while_ループが機能することも知っていますが、そのようなforループを書くことができるかどうか気になりますか?また、SOには答えがないようなので、私は質問することにしました:)


更新:2つ目の条件では_!A_がfalseになるため、少なくとも2つの削除された回答で提案された「明白な」バリアントfor(bool A=false; !A; A=true)は1回の反復のみを実行することに注意してください。ループが終了します。

じっくり考えた後、C++ 03では、2番目の変数や、DietmarKühlが提案したようなポインターベースのコンストラクトがないと、それは不可能だと思います。目的の実行で条件を3回テストする必要があるため、ブール値の2つの値だけでは不十分です。また、最初の反復が無条件に実行されるため、do-whileループが機能し、条件は2回しかチェックされないため、ブール値を使用して続行と終了を選択できます。

48
Alexey Kukanov

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


これはC++ 03バージョンです。

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

aまたはbを使用してください。)

59
Kerrek SB

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);
}
7
Dietmar Kühl
for (int a = 0; a <= 1; a++)
  doStuff(a ? true : false);

そして、「他の型への変換なし」の制限を忘れてください:)結局のところ、明確さは人為的な制限よりも重要です。 5年後、自分のコードを読んで、「一体何を考えていたのか、これはある種の難読化コンテストなのか?」

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

OK、それはforループではありませんが、forループの提案(もちろんC++ 11のアプローチ以外)のどれよりも読みやすいと思います。

4
mdk

C++ 03のもう1つ:

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

Bを使用します。

2
Aotium

この回答は、「不可能」なC++ 03、単一変数のみのソリューションに対処します

最初に、単一の入力変数のみに依存する決定論的な算術式が両方の入力true,falseに当てはまることはできないが、trueまたはfalse

ただし、「不正行為」は可能です。ただし、私が実際に不正行為をしていることを証明してください。

#include <iostream>

using namespace std;

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

これは確かに未定義の動作のように見えます。 C++ 03は少し 不明確 です。ただし、sizeofは常に少なくとも1でなければなりません(長さ0のvar-len配列の非標準の例外を除く)。さらに、各文字が少なくとも8ビットであることが保証されているため、2番目の文字をカウンターに使用できます。

実際、これを行うには、決定論を回避する(false, trueを1回だけ繰り返すという保証をあきらめない限り)か、制約型システムを使用する必要があります。

2
VF1

これも機能します:

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

(@KerrekSBの逆ソリューションの一種)

1
jrok

他のタイプに変換せずに解決策を求めたのは知っていますが、「流用されていない他のタイプに変換せずに」という意味だと思います。これは、この特定のケースで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);
0
Caduchon