Do the &= and |= operators for bool short-circuit? - c++

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.

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.

The short-circuit (i.e. lazy) evaluation is only for logical && and ||. Bitwise & and | evaluate both arguments.

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.

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.

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++.

Since & is a bit operation, check_foo()` will be evaluated irrespective of value of result
result = false;
result &= check_foo(); // check_foo() is needless called
However, check_foo() will not be called if you use && and result is false as in:
result = false;
result = result && check_foo(); // check_foo() is not called, the bitwise operator shortcircuits

Related

Are bitwise and logical operations the same for bool type?

C++ has logical operations, !a, a && b, a || b applicable to true/false values.
And it has bitwise operations, applicable to all (integer?) types, ~a, a & b, a | b, a ^ b, (a << N, a >> N).
Together with in place mutation operators, a &= b, a |= b, a ^= b, (a <<= b, a >>= b).
What confuses me is that bitwise operations could be acting on bits of bool that are not at all part of the true/false value.
Even doing unnecessary bit operations.
I guess that last fact makes bitwise shifting undefined for bool and that makes me doubt whether all bitwise operations are valid at all.
So, are these equivalent for bool types? ~a == !a, a && b == a & b, a || b == a | b?
For some reason (won't question here) there is no "in-place" logical mutation operators (i.e. a &&= b, a ||= b).
This inspires these questions, are these other bitwise operations valid on bools themselves? are a &= b and a |= b always equivalent to a = a && b and a = a || b respectively?** (no "in-place" xor a = a ^ b?)
Some examples: https://godbolt.org/z/hcccG8c9o
(For simplicity I will assume C++20, i.e. two's complement representation of integer types. What I am writing may technically not hold prior to C++20 for all theoretically possible conforming representations of integer types.)
What confuses me is that bitwise operations could be acting on bits of bool that are not at all part of the true/false value.
The built-in bitwise operations have the usual arithmetic conversions applied to their operands first. For integral operands that implies integral promotions: Operands with a conversion rank below that of int are converted to int first (or unsigned int or a higher rank integral type if int can't hold all values of the original type).
The promotion always leaves the original value unchanged. In the case of bool, true is mapped to 1 and false to 0. So the result after promotion will have its least significant bit either set or unset, while all other bits are unset. Also, there are always at least 15 such bits, because int must be at least 16 bit wide.
As a consequence ~a == !a is always false. ~ will set these additional bits, while promotion of !a will not. However bool(~a) == bool(!a) is true only if a is false, because with additional bits set bool(~a) is always true.
a && b == a & b is always true, because additional bits will be zero when & is applied.
a || b == a | b is always true, because additional bits will again remain zero.
However, if a and b are actual expressions, then there is another difference in that the logical operators short-circuit evaluation, while the bitwise ones don't. Therefore, the side effects may be different.
Also, the result of the logical operators will be a bool, while that of the bitwise ones will be a int. Therefore they are not interchangeable as they might e.g. affect overload resolution where their result is used.
Also, this applies only for the built-in operators. If any overloaded operators are involved, nothing is guaranteed.

Is there any ternary operator for just single if condition in dart?

In dart we have plenty of ternary operators.
But do we have one ternary operator just for if condition?
Example
In condition
if (num == 1){
print(true);
} else {
print(false);
}
In ternary
print(num == 1 ? true : false);
So do we have any ternary operator just for true condition like above example?
if (num == 1) {
print(true);
}
No.
The conditional operator ?/: in Dart requires all three operands.
It does so because all expressions must have a value, and if you could do just e1 ? e2, then the expression has no value if e1 is false.
It's not impossible to conceive of a binary conditional operator where the missing expression defaults to null, say (e1?:elseExpression) or (e1?thenExpression:), but then you can also just write the null, and saving four letters is probably not worth the potential loss of readability.
Ob-nitpick. The conditional operator in Dart is one of two ternary operators (operators requiring three operands, like binary operators require two operands), the other ternary operator being []=.
I wonder, since && is short-circuiting, we can use:
b && f(args) to replace if(b){ f(args);}
Where if b is true, function f will be executed. The drawback is that f must return a bool. A true() wrapper function could be used.

In what order are expressions in an `if` condition evaluated? [duplicate]

if(a && b)
{
do something;
}
is there any possibility to evaluate arguments from right to left(b -> a)?
if "yes", what influences the evaluation order?
(i'm using VS2008)
With C++ there are only a few operators that guarantee the evaluation order
operator && evaluates left operand first and if the value is logically false then it avoids evaluating the right operand. Typical use is for example if (x > 0 && k/x < limit) ... that avoids division by zero problems.
operator || evaluates left operand first and if the value is logically true then it avoids evaluating the right operand. For example if (overwrite_files || confirm("File existing, overwrite?")) ... will not ask confirmation when the flag overwrite_files is set.
operator , evaluates left operand first and then right operand anyway, returning the value of right operand. This operator is not used very often. Note that commas between parameters in a function call are not comma operators and the order of evaluation is not guaranteed.
The ternary operator x?y:z evaluates x first, and then depending on the logical value of the result evaluates either only y or only z.
For all other operators the order of evaluation is not specified.
The situation is actually worse because it's not that the order is not specified, but that there is not even an "order" for the expression at all, and for example in
std::cout << f() << g() << x(k(), h());
it's possible that functions will be called in the order h-g-k-x-f (this is a bit disturbing because the mental model of << operator conveys somehow the idea of sequentiality but in reality respects the sequence only in the order results are put on the stream and not in the order the results are computed).
Obviously the value dependencies in the expression may introduce some order guarantee; for example in the above expression it's guaranteed that both k() and h() will be called before x(...) because the return values from both are needed to call x (C++ is not lazy).
Note also that the guarantees for &&, || and , are valid only for predefined operators. If you overload those operators for your types they will be in that case like normal function calls and the order of evaluation of the operands will be unspecified.
Changes since C++17
C++17 introduced some extra ad-hoc specific guarantees about evaluation order (for example in the left-shift operator <<). For all the details see https://stackoverflow.com/a/38501596/320726
The evaluation order is specified by the standard and is left-to-right. The left-most expression will always be evaluated first with the && clause.
If you want b to be evaluated first:
if(b && a)
{
//do something
}
If both arguments are methods and you want both of them to be evaluated regardless of their result:
bool rb = b();
bool ra = a();
if ( ra && rb )
{
//do something
}
In this case, since you're using &&, a will always be evaluated first because the result is used to determine whether or not to short-circuit the expression.
If a returns false, then b is not allowed to evaluate at all.
Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.
Read here for a more exhaustive explanation of the rules set:
order evaluation
It will evaluate from left to right and short-circuit the evaluation if it can (e.g. if a evaluates to false it won't evaluate b).
If you care about the order they are evaluated in you just need to specify them in the desired order of evaluation in your if statement.
The built-in && operator always evaluates its left operand first. For example:
if (a && b)
{
//block of code
}
If a is false, then b will not be evaluated.
If you want b to be evaluated first, and a only if b is true, simply write the expression the other way around:
if (b && a)
{
//block of code
}

"|=" what does this mean and what is this called? (c++)

void show_node_names() { display_flags |= ShowNodeNames; } // what is "|="?
I'm not sure what "|=" does or what it's called.
Any help?
That statement is a bitwise or assignment.
It is equivalent to doing display_flags = display_flags | ShowNodeNames.
In particular, it will set every bit in display_flags to 1 if the corresponding bit in ShowNodeNames is 1.
The |= operator is a compound assignment operator like += or *=, but using the bitwise OR operator. The line
display_flags |= ShowNodeNames;
is equivalent to
display_flags = display_flags | ShowNodeNames;
If you haven't seen the bitwise OR operator, you should read up on it for more details. If you're familiar with it, then you can think of display_flags |= ShowNodeNames; as a way of saying "make all the bits set in ShowNodeNames also set in display_flags."
Hope this helps!
| (which can also be spelt bitor) is the bitwise or operator. It combines the bits of each operand so that each bit of the output is set if the corresponding bit of either operand is set. Compare this with the bitwise and operator, & or bitand, where each bit is set of the corresponding bit of both operands is set.
|= (or or_eq) is the corresponding assignment operator. As with all compound assignment operators, a |= b is equivalent to a = a | b, except that a is only evaluated once. Its effect is to set each bit in a that's set in b, and leave the other bits unchanged.

"IF" argument evaluation order?

if(a && b)
{
do something;
}
is there any possibility to evaluate arguments from right to left(b -> a)?
if "yes", what influences the evaluation order?
(i'm using VS2008)
With C++ there are only a few operators that guarantee the evaluation order
operator && evaluates left operand first and if the value is logically false then it avoids evaluating the right operand. Typical use is for example if (x > 0 && k/x < limit) ... that avoids division by zero problems.
operator || evaluates left operand first and if the value is logically true then it avoids evaluating the right operand. For example if (overwrite_files || confirm("File existing, overwrite?")) ... will not ask confirmation when the flag overwrite_files is set.
operator , evaluates left operand first and then right operand anyway, returning the value of right operand. This operator is not used very often. Note that commas between parameters in a function call are not comma operators and the order of evaluation is not guaranteed.
The ternary operator x?y:z evaluates x first, and then depending on the logical value of the result evaluates either only y or only z.
For all other operators the order of evaluation is not specified.
The situation is actually worse because it's not that the order is not specified, but that there is not even an "order" for the expression at all, and for example in
std::cout << f() << g() << x(k(), h());
it's possible that functions will be called in the order h-g-k-x-f (this is a bit disturbing because the mental model of << operator conveys somehow the idea of sequentiality but in reality respects the sequence only in the order results are put on the stream and not in the order the results are computed).
Obviously the value dependencies in the expression may introduce some order guarantee; for example in the above expression it's guaranteed that both k() and h() will be called before x(...) because the return values from both are needed to call x (C++ is not lazy).
Note also that the guarantees for &&, || and , are valid only for predefined operators. If you overload those operators for your types they will be in that case like normal function calls and the order of evaluation of the operands will be unspecified.
Changes since C++17
C++17 introduced some extra ad-hoc specific guarantees about evaluation order (for example in the left-shift operator <<). For all the details see https://stackoverflow.com/a/38501596/320726
The evaluation order is specified by the standard and is left-to-right. The left-most expression will always be evaluated first with the && clause.
If you want b to be evaluated first:
if(b && a)
{
//do something
}
If both arguments are methods and you want both of them to be evaluated regardless of their result:
bool rb = b();
bool ra = a();
if ( ra && rb )
{
//do something
}
In this case, since you're using &&, a will always be evaluated first because the result is used to determine whether or not to short-circuit the expression.
If a returns false, then b is not allowed to evaluate at all.
Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.
Read here for a more exhaustive explanation of the rules set:
order evaluation
It will evaluate from left to right and short-circuit the evaluation if it can (e.g. if a evaluates to false it won't evaluate b).
If you care about the order they are evaluated in you just need to specify them in the desired order of evaluation in your if statement.
The built-in && operator always evaluates its left operand first. For example:
if (a && b)
{
//block of code
}
If a is false, then b will not be evaluated.
If you want b to be evaluated first, and a only if b is true, simply write the expression the other way around:
if (b && a)
{
//block of code
}