if statement - short circuit evaluation vs readability
Solution 1:
One natural solution would look like this:
bool b1 = SomeCondition();
bool b2 = b1 || SomeOtherCondition();
bool b3 = b2 || SomeThirdCondition();
// any other condition
bool bn = bn_1 || SomeFinalCondition();
if (bn)
{
// do stuff
}
This has the benefits of being easy to understand, being applicable to all cases and having short circuit behaviour.
This was my initial solution: A good pattern in method calls and for-loop bodies is the following:
if (!SomeComplicatedFunctionCall())
return; // or continue
if (!SomeOtherComplicatedFunctionCall())
return; // or continue
// do stuff
One gets the same nice performance benefits of shortcircuit evaluation, but the code looks more readable.
Solution 2:
I tend to break down conditions onto multiple lines, i.e.:
if( SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()
) {
Even when dealing with multiple operators (&&) you just need to advance indention with each pair of brackets. SCE still kicks in - no need to use variables. Writing code this way made it much more readible to me for years already. More complex example:
if( one()
||( two()> 1337
&&( three()== 'foo'
|| four()
)
)
|| five()!= 3.1415
) {
Solution 3:
If you have long chains of conditions and what to keep some of the short-circuiting, then you could use temporary variables to combine multiple conditions. Taking your example it would be possible to do e.g.
bool b = SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
if (b && some_other_expression) { ... }
If you have a C++11 capable compiler you could use lambda expressions to combine expressions into functions, similar to the above:
auto e = []()
{
return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
};
if (e() && some_other_expression) { ... }
Solution 4:
1) Yes, you no longer have SCE. Otherwise, you would have that
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
works one way or the other depending if there is an if
statement later. Way too complex.
2) This is opinion based, but for reasonably complex expressions you can do:
if (SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()) {
If it ways too complex, the obvious solution is to create a function that evaluates the expression and call it.
Solution 5:
You can also use:
bool b = someComplicatedStuff();
b = b || otherComplicatedStuff(); // it has to be: b = b || ...; b |= ...; is bitwise OR and SCE is not working then
and SCE will work.
But it's not much more readable than for example:
if (
someComplicatedStuff()
||
otherComplicatedStuff()
)