title: C++ difference in behavior between if statement setting condition to true and or-ing a condition in loop
body: <p>I was working on Datalog interpreter for my CS class and I ran into a strange problem where my Rule evaluations took too many passes to complete. After looking at my code I made two modifications in the following that fixed my evaluations to execute in the correct number of passes:</p>
  
  <pre><code>//original form
  bool addedFacts = false;
  for (X x: xs) {
      addedFacts = addedFacts || set.insert(x).second;
  }
  //modified form
  bool addedFacts = false;
  for (X x: xs) {
      if (set.insert(x).second) {
          addedFacts = true;
      }
  }
  </code></pre>
  
  <p>To me these two code structures appear logically equivalent. Is there a reason why one executes correctly and one execute incorrectly/inefficiently?
  Here is a buildable example of the problem that was occurring:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;set&gt;
  #include &lt;vector&gt;
  
  using std::set;
  using std::vector;
  using std::cout;
  using std::endl;
  
  const int CAP = 100;
  
  class Rule {
  public:
      int factor;
      Rule(int factor) {
          this-&gt;factor = factor;
      }
      bool evaluateInefficient(set&lt;int&gt;&amp; facts) {
          vector&lt;int&gt; data;
          bool addedFacts = false;
          for (int fact : facts) {
              data.push_back(fact);
          }
          for (int datum : data) {
              int newFact = datum * factor;
              if (newFact &lt; CAP) {
                  addedFacts = addedFacts || facts.insert(newFact).second;
              }
          }
          return addedFacts;
      }
      bool evaluate(set&lt;int&gt;&amp; facts) {
          vector&lt;int&gt; data;
          bool addedFacts = false;
          for (int fact : facts) {
              data.push_back(fact);
          }
          for (int datum : data) {
              int newFact = datum * factor;
              if (newFact &lt; CAP) {
                  if (facts.insert(newFact).second) {
                      addedFacts = true;
                  }
              }
          }
          return addedFacts;
      }
  };
  
  int doublyInefficient(vector&lt;Rule&gt;&amp; rules) {
      set&lt;int&gt; facts;
      facts.insert(1);
      bool addedFacts = true;
      int passes = 0;
      while (addedFacts) {
          passes++;
          addedFacts = false;
          for (Rule rule : rules) {
              addedFacts = addedFacts || rule.evaluateInefficient(facts);
          }
      }
      return passes;
  }
  
  int singlyInefficient(vector&lt;Rule&gt;&amp; rules) {
      set&lt;int&gt; facts;
      facts.insert(1);
      bool addedFacts = true;
      int passes = 0;
      while (addedFacts) {
          passes++;
          addedFacts = false;
          for (Rule rule : rules) {
              addedFacts = addedFacts || rule.evaluate(facts);
          }
      }
      return passes;
  }
  
  int efficient(vector&lt;Rule&gt;&amp; rules) {
      set&lt;int&gt; facts;
      facts.insert(1);
      bool addedFacts = true;
      int passes = 0;
      while (addedFacts) {
          passes++;
          addedFacts = false;
          for (Rule rule : rules) {
              if (rule.evaluate(facts)) {
                  addedFacts = true;
              }
          }
      }
      return passes;
  }
  
  int main(int argc, char* argv[]) {
      //build the rules
      vector&lt;Rule&gt; rules;
      rules.push_back(Rule(2));
      rules.push_back(Rule(3));
      rules.push_back(Rule(5));
      rules.push_back(Rule(7));
      rules.push_back(Rule(11));
      rules.push_back(Rule(13));
      //Show three different codes that should (in my mind) take the same amount of passes over the rules but don't
      cout &lt;&lt; "Facts populated after " &lt;&lt; doublyInefficient(rules) &lt;&lt; " passes through the Rules." &lt;&lt; endl;
      cout &lt;&lt; "Facts populated after " &lt;&lt; singlyInefficient(rules) &lt;&lt; " passes through the Rules." &lt;&lt; endl;
      cout &lt;&lt; "Facts populated after " &lt;&lt; efficient(rules) &lt;&lt; " passes through the Rules." &lt;&lt; endl;
      getchar();
  }
  </code></pre>
  
  <p>I get the following output when running in debug and release mode (32-bit) on visual studio 2017. To my knowledge the code is not optimized.</p>
  
  <pre><code>Facts populated after 61 passes through the Rules.
  Facts populated after 17 passes through the Rules.
  Facts populated after 7 passes through the Rules.
  </code></pre>