0

At my work I tried to use this construction:

if (repl && (repl = replaced.count(*l))) {
    // repl isn't used here 
    ...
}

and in my mind it should work the same way as

bool newRepl = replaced.count(*l);
if (repl && newRepl) {
    // repl isn't used here 
    ...
}
repl = newRepl;

because expressions in && evaluate from left to right, but unexpectedly it's not.
Is it a not specified construction in C++ or I don't correctly understand how it should work?

Example of code with a problem:

std::set<int> set{3, 4, 6};
bool repl = false;
for (size_t i = 3; i < 7; ++i) {
    if (repl && (repl = set.count(i))) {
        std::cout << "strangeif" << std::endl;
    }
}

output:

std::set<int> set{3, 4, 6};
bool repl = false;
for (size_t i = 3; i < 7; ++i) {
    bool newRepl = set.count(i);
    if (repl && newRepl) {
        std::cout << "strangeif" << std::endl;
    }
    repl = newRepl;
}

output: strangeif

  • https://en.wikipedia.org/wiki/Short-circuit_evaluation – KamilCuk Nov 25 '21 at 12:23
  • There is nothing strange. The first code you wrote is fundamentally different than what you wrote as to how you thought it should work. [See this for a similar example](https://stackoverflow.com/questions/34306879/c-iterator-stuck-at-first-value) There is no guarantee that `(repl = replaced.count(*l))` will be executed, due to short circuit evaluation. Most, if not all computer languages will not execute the right hand side of a logical and, if it detects that the left side of the logical and is false. – PaulMcKenzie Nov 25 '21 at 12:25
  • to give you a really short and clear answer. left && right -> when left is false the right isn't never checked. – IkarusDeveloper Nov 25 '21 at 12:42

2 Answers2

8

&& is short-circuiting. Your original code is equivalent to this:

if (repl) {
   repl = replaced.count(*l))
   if (repl) {
    // repl isn't used here 
    ...
  }
}
Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
0

In addition to the answer of @Sebastian Redl which is also a good answer, i would like to clearify the concept. the following code would help to understand the concept of short-circuiting.

#include <iostream>

bool printret(bool ret){
    std::cout << "printret call: " << ret << std::endl;
    return ret;
}


int main()
{
    std::cout << "first test :" << std::endl;
    if(printret(true) && printret(false)){}

    std::cout << "second test:" << std::endl;
    if(printret(false) && printret(true)){}
    return 0;
}

Output :

first test :
printret call: 1
printret call: 0
second test:
printret call: 0

the second test is literally ignoring the expression in the right side of && since the first expression (in the left side of &&) returns false.

IkarusDeveloper
  • 369
  • 4
  • 8