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()
   )