Do the &= and |= operators for bool short-circuit?
C++BooleanLazy EvaluationShort CircuitingCompound AssignmentC++ Problem Overview
When writing code like this in C++:
bool allTrue = true;
allTrue = allTrue && check_foo();
allTrue = allTrue && check_bar();
check_bar()
will not be evaluated if check_foo()
returned false
. This is called short-circuiting or short-circuit evaluation and is part of the lazy evaluation principle.
Does this work with the compound assignment operator &=
?
bool allTrue = true;
allTrue &= check_foo();
allTrue &= check_bar(); //what now?
For logical OR
replace all &
with |
and true
with false
.
C++ Solutions
Solution 1 - C++
From C++11 5.17 Assignment and compound assignment operators
:
> The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
However, you're mixing up logical AND which does short-circuit, and the bitwise AND which never does.
The text snippet &&=
, which would be how you would do what you're asking about, is nowhere to be found in the standard. The reason for that is that it doesn't actually exist: there is no logical-and-assignment operator.
Solution 2 - C++
The short-circuit (i.e. lazy) evaluation is only for logical &&
and ||
. Bitwise &
and |
evaluate both arguments.
Solution 3 - C++
No, they do not cut-short.
Note that the &=
and |=
operators are formed as &
+=
and |
+=
. Bit operators &
and |
does not perform shortcut evaluation.
Only boolean operators &&
and ||
perform it.
It means, that a shortcutting operator would have to be traditionally named &&=
and ||=
. Some languages provide them. C/C++ does not.
Solution 4 - C++
The code allTrue &= check_foo();
is equivalent to allTrue = allTrue & check_foo()
In which you are using bitwise AND
and no lazy evaluation is performed.
The bitwise AND
must take two arguments who's binary representation has the same length, and useslogical AND
operation to compare each corresponding pair of bits.
Solution 5 - C++
First: a &= b;
is not the same as a = a && b;
. a &= b;
means a = a & b;
. In C/C++ there is no a &&= b;
.
Logical AND a && b
is bit like a test for 1 bit. If the first "bit" is already 0, than the result will always be 0 no matter the second. So it is not necessary to evaluate b
if the result is already clear from a
. The C/C++ standard allows this optimization.
Bitwise AND a & b
performs this test for all bits of a
and b
. So b
needs to be evaluated if at least one bit in a
would be non-zero. You could perhaps wish that if a==0
, than b
would not be evaluated, but this optimization is not allowed in C/C++.
Solution 6 - C++
Since & is a bit operation, check_foo() will be evaluated first irrespective of value of allTrue in
allTrue &= check_foo(); // also for allTrue = allTrue & check_foo();
and also
allTrue &= check_bar(); // also for allTrue = allTrue & check_bar();
However, check_foo() will not be called if you use && and alltrue is false as in:
allTrue = allTrue && check_foo();