1

Probably a very simple question but I'm interested in what options there are. I have three conditions each of which should produce a different output

// special cases
if(!A && B)
     return -1;
if(A && !B)
     return 1;
if(!A && !B)
     return 0;

// general case
return someOtherFunction(x, y);

Which I can get down to -

if(!A) {
    if(!B)
        return 0;
     return -1;
}
if(A && !B)
    return 1;

return someOtherFunction(x, y);

Can I simplify this further? This is in C++ so I am limited to using language specific operators and functions (including STL) etc.

Madden
  • 1,024
  • 1
  • 9
  • 27

4 Answers4

5
return (!A ? (!B ? 0 : -1) : (!B ? 1 : someOtherFunction(x, y)));

This is using nested ternary operator.

Community
  • 1
  • 1
CinCout
  • 9,486
  • 12
  • 49
  • 67
  • 3
    What about `someOtherFunction` call? If `A` is true, and `B` is also true - this expression will fail to call the other function. – Ajay May 25 '16 at 11:03
  • @Ajay Updated the answer to include the case that the OP added later. This is what happens when OP edits a question, without mentioning that it is, in fact, an edit! – CinCout May 25 '16 at 16:57
4

Use look-up table:

int lookup[2][2] = {
    { 0, -1}
,   { 1,  100}
};
...
bool A, B;
A = ...
B = ...
...
int res = lookup[A][B];
// When A && B, call other function
return res != 100 ? res : someOtherFunction(a, b);

Note: If A and B are not Boolean, convert them to logical values with the double-negation trick:

return lookup[!!A][!!B];
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • No one said it should be readable ;-). @dasblinkenlight. You could add a second lookup table with bools. And write it like: ```return lookupBool[A][B]?lookupInt[A][B]:someOtherFunction(A, B)``` – Gene May 25 '16 at 11:07
  • Your code is overly complicated - it doesn't simplify, but complicates the code. Other solution (ternary) is simply not correct. – Ajay May 25 '16 at 11:08
  • 1
    @Gene Readability is in the eye of the reader. To me, look-up tables are far more readable than a chain of three conditionals. This may not be the perfect example because OP has only two variables, but with three or more variables table look-up becomes clearly superior. – Sergey Kalinichenko May 25 '16 at 11:12
  • 1
    @Ajay Admittedly, there is very little to simplify about code with two logical variables. However, once the number of variables goes up to three or more, maintainability of `if` chains quickly deteriorates to the point of becoming nightmare. Lookup tables are free from this problem. They also give you a branch-free solution in situations when you do not need to call `someOtherFunction`. – Sergey Kalinichenko May 25 '16 at 11:15
  • 1
    @dasblinkenlight I totally agree. I think your code is perfectly fine. Especially because we don't know the context the whole expression will be used at the end. Also if this code is repeated in different ways at a lot of places, reducing amount of lines of code is very helpfull. – Gene May 25 '16 at 11:16
  • @Gene, I do understand the importance of lookup tables, and I've also used it many times. But for this simple problem, my eyes hurt. At least you could have used small-sized variables, `const` or `constexpr` :) – Ajay May 25 '16 at 11:18
3

So interestingly the case if (A and B) is not defined.

I would use following solution, since boolean can be converted to ints.

return A - B;

Edit: the original question changed. In that case I would do:

if (!A or !B)
    return A - B;
return someOtherFunction(A, B);
Gene
  • 410
  • 5
  • 16
  • Or with the double negation trick from @dasblinkenlight . `return (!!A) - (!!B);` – Gene May 25 '16 at 11:00
  • I quite like this as it is fairly readable but also quite elegant, my only question is whether this (implicit casting of bools for comparison) is hacky? – Madden May 25 '16 at 11:14
  • I'm not hundred percent sure, but it seems like the conversion from bools to ints is well defined in c++. See this answer: http://stackoverflow.com/a/5369783/1293111 – Gene May 25 '16 at 11:19
  • @Madden, Yes, it is well defined. Be careful though. If A and B are not variables but function calls (it is not obvious from your question) with side effects then this code will have UB. –  May 25 '16 at 11:35
  • @DmitryKuznetsov, same goes for the call ```someOtherFunction(A, B)``` which has UB anyway, if A and B are functions and they have sideeffects that interfere with each other. – Gene May 25 '16 at 11:47
  • A and B are const booleans returned by a function call, someOtherFunction is passed different parameters not A and B, have edited the op for calirty – Madden May 25 '16 at 12:22
3

I would suggest you to keep it as is for the sake of readability and understanding by the fellow programmer (which might be you). Don't optimize unnecessarily unless really needed. In this case, you don't get any real advantage.

One thing you could do is to store result of A and B into variables (if they are function calls).

Ajay
  • 18,086
  • 12
  • 59
  • 105