8

I have written a program that lists errors in a set of stuff, and returns a boolean value at the end (returning true means that no error has been found).

Here is a summary of my code :

bool checkStuff1() {/*...*/}
bool checkStuff2() {/*...*/}
// ...
bool checkStuffN() {/*...*/}

bool checkAllStuff()
{
    bool result = true;
    result &= checkStuff1();
    result &= checkStuff2();
    // ...
    result &= checkStuffN();
    return result;
}

I have confidence the value of result will be the right one at the end. However, I would like to be sure that all the functions checkStuffX() are called (because they print error messages when failing, and I would like all the error messages to be printed).

I know that if I wrote this way, it would skip all checkStuffX() after the first one failing :

result = result && checkStuffX(); // Will not call checkStuffX() if result is already false

I also know that if I wrote this way, it will call all checkStuffX() functions :

result = checkStuffX() && result; // Will always call checkStuffX() even if result is false

But I was wondering if the behaviour of the code I am using, with bitwise comparison, was determined and guaranteed by the standard ?

Or is there a risk of undefined behaviour, depending on the compiler used and its optimisations ?

vsoftco
  • 55,410
  • 12
  • 139
  • 252
teupoui
  • 293
  • 3
  • 15
  • 1
    You may also use `bool failed=false; failed|=!checkStuff1(); failed|=!checkStuff2();...failed|=!checkStuffN();return !failed;`. This follows the simple rule of (A&&B) = !(!A || !B) – Simon Kraemer Nov 24 '16 at 18:23

2 Answers2

9

This is perfectly fine.

Short-circuit evaluation, to which you're referring to, applies only to the && and || operators.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Related: http://stackoverflow.com/questions/2488406/why-doesnt-c-have-or-for-booleans – Simon Kraemer Nov 24 '16 at 18:27
  • Is there something that guarantees there will be no short-circuit evaluation (or similar optimisation) in any case with operator&= ? I mean, X &= Y with X == 0 will always end up with X == 0 whatever the value of Y. I would like to be sure that, whatever compiler is used, the behavior will be the same one everywhere, and Y() will be called if it is a function. Is there something in the standards that guarantees it ? – teupoui Nov 25 '16 at 09:34
  • Yes, it's guaranteed by the definition of boolean algebra. If all bits in one operand are 0, the result of the bitwise `&` operator is guaranteed to be 0. – Sam Varshavchik Nov 25 '16 at 15:05
  • Thanks Sam, but my question is not about the result, I know it will return false eventually. My question is about the call to function Y() in expression `X &= Y()` where `X == 0`. How can I be 100% sure Y() will be called ? – teupoui Nov 25 '16 at 15:35
  • I don't know of any other way to say "yes". The C++ language specification specifies short circuit evaluation only for `&&` and `||` operators. End of story. – Sam Varshavchik Nov 25 '16 at 15:42
0

It would work, though conversion int<->bool maybe performance issue, if you have many checks. Oh, you may take advantage of function pointers and for loop, if all functions have same type.

bool  (*checks[])( void )= {checkStuff1, checkStuff2 ...  checkStuffN};

bool result = true;
for (int i = 0; i < sizeof(checks)/sizeof(checks[0]); result = checks[i++]() && result );

Code would look simpler if you can use ranged for() - like for(auto i : checks). Advantage of that if you have that procedure declared somewhere else in code, need to remove or add a step, you just modify declaration of the array (or your program can change it, effectively changing the workflow!). Downside - you can't use it with checks that have different prototypes.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • That would not help me much in my case... I have simplified my question : the checking functions take different parameters each time. But thanks anyway ! – teupoui Nov 25 '16 at 09:36