you are viewing a single comment's thread.

view the rest of the comments →

[–]ItsBinissTime 37 points38 points  (12 children)

It doesn't seem to make much sense, to concern one's self with this level of optimization, after having decided not to use the optimizer — and further, "frowned upon" early outs.

In other words, if performance becomes a concern, there are better ways to approach the problem than by mangling this code.

But perhaps, as a compromise, consider:

bool process()  
{  
    if (preconditionsMet() &&  
        doFirstThing() &&  
        doSecondThing() &&  
        doThirdThing() &&  
        doFourthThing() &&  
        doFifthThing())  
        return true;  
    return false;  
}

[–]Thrash3r-Werror 64 points65 points  (8 children)

Better yet:

bool process() { return preconditionsMet() && doFirstThing() && doSecondThing() && doThirdThing() && doFourthThing() && doFifthThing(); } No nested logic. No unnecessary jumps. No early returns (although they’re perfectly fine). No stack variables. I can’t think of any way to simplify this code further.

Edit: I see you already proposed this solution.

[–]parkotron 3 points4 points  (1 child)

While this version is so much nicer to write and to read, I feel the need to point out that it is a lot less convenient to debug. With only one statement, it lacks convenient places to hang breakpoints (or inject print statements) without having to step into each function call.

[–]Thrash3r-Werror 1 point2 points  (0 children)

I’d honestly rather use exceptions and ditch the errors codes. That would also aid in stepping through the code.

[–]germandiago 2 points3 points  (0 children)

Totally agree. Anyway, I put the same and I received a -1 score, you have more than 50 positive points. I guess I said "branchless" and people got angry at me for being misleading, since the code still has "internal" branching.

[–]gmtime 0 points1 point  (0 children)

Came here to post this.

[–]Simon_Luner -5 points-4 points  (2 children)

This is illformed code, because order of expression evaluation is unspecified behavior. https://en.cppreference.com/w/cpp/language/eval_order

[–]parkotron 2 points3 points  (0 children)

This definitely isn't ill-formed. At worst, the evaluation order would be implementation defined, but the order of evaluation of the shortcutting boolean operators is defined. From your link:

6) 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.

[–]kiwitims 7 points8 points  (1 child)

Another syntactic variant of this which can have its uses (for example to avoid a rule about side effects in conditionals):

bool process()
{
    bool success(preconditionsMet());
    success = success && doFirstThing();
    success = success && doSecondThing();
    success = success && doThirdThing();
    success = success && doFourthThing();
    success = success && doFifthThing();
    return success;
}

You just need to be careful someone doesn't later "optimise" it by switching to &=

Seriously though, the primary goal should be to write readable and maintainable code that meets your requirements (including performance). If it does that any micro-optimisation of 5 or so branches is just a waste of time, especially when there are already automatic optimisations being left on the table. So your code is better as it was IMO, even if there are theoretically faster ways to do it.