Mdp11
Mdp11

Reputation: 572

Simplify 4 if/else checks on two booleans

I have a situation like this in my code:

bool a, b, result;
... // a and b are set
if(!a &&! b)
    result = functionOne() ;
else if(!a && b)
    result = functionTwo();
else if(a &&! b)
    result = functionThree();
else
    result = functionFour();

Is there any way to simplify/shorten this code? Thanks in advance!

Upvotes: 0

Views: 729

Answers (5)

Peter
Peter

Reputation: 36597

This question is really opinion based, so there are many possible solutions that - depending on individual preferences - may be chosen.

You can always test a single variable in the if, and then use a ternary operator

 if (!a)
     result = (!b) ? functionOne() : functionTwo();
 else
     result = (!b) ? functionThree() : functionFour();

This has a (possible) advantage of only needing to evaluate each of !a and !b exactly once at run time.

If you want to eliminate the negations (some may consider that is better for readability, particularly since it is unusual for the names of functions to imply an ordering of them) the code can be turned into

 if (a)
     result = b ? functionFour() : functionThree();
 else
     result = b ? functionTwo() : functionOne();

which brings us to options of eliminating the if statement entirely.

 // with negation

 result = !a ? ((!b) ? functionOne() : functionTwo()) : 
              ((!b) ? functionThree() : functionFour());

 // without negation

 result = a ? (b ? functionFour() : functionThree()) : 
              (b ? functionTwo() : functionOne());

Another option that comes to mind would be

 int index = 2*a + b;
 if (index == 0)
     result = functionOne();
 else if (index == 1)
     result = functionTwo();
 else if (index == 2)
     result = functionThree();
 else if (index == 3)
     result = functionFour();

which can be simplified by using a one dimensional array

  using func = bool(*)();    // C++11 and later.   typedef bool (*func)() for all C++ standards
  func table[] = {functionOne, functionTwo, functionThree, functionFour};
  result = table[2*a + b]();

Upvotes: 2

Loki Astari
Loki Astari

Reputation: 264331

Use a switch:

 int index = 2*a + b;
 switch (index) {
     case 0: result = functionOne();  break;
     case 1: result = functionTwo();  break;
     case 2: result = functionThree();break;
     case 3: result = functionFour(); break;
 }

Upvotes: 2

ItsMeMario
ItsMeMario

Reputation: 26

Yes, you can use the ternary operator:

bool a, b, result;
// a and b are set
result = a && b ? functionOne() : b ?functionTwo() : a ? functionThree() : functionFour();

Use it only for simple if else tasks and not for complicated ones because it's can get messy really fast.

Upvotes: 1

Picaud Vincent
Picaud Vincent

Reputation: 10982

As learning is your purpose here is a "simplification" using lookup table:

#include <iostream>

bool functionOne()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionTwo()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionThree()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}
bool functionFour()
{
  std::cout << __FUNCTION__ << std::endl;
  return true;
}

int main()
{
  using F = bool (*)();
  constexpr F lookup[2][2] = {{functionOne, functionTwo},
                              {functionThree, functionFour}};

  bool a = true, b = false, result;
  result = lookup[a][b]();           // <- the simplification
}

prints:

functionThree

as expected.

Explanation: it uses a 2-dimensional array of function pointers.

Note: it works as C++ standard explicitly says that during conversion bool -> int (your array index), false is converted to zero and true to one.

If the source type is bool, the value false is converted to zero and
the value true is converted to the value one of the destination type
(note that if the destination type is int, this is an integer
promotion, not an integer conversion).

https://en.cppreference.com/w/cpp/language/implicit_conversion

Upvotes: 2

Ulrich Eckhardt
Ulrich Eckhardt

Reputation: 17415

Yes, you can make use of some implications:

bool a, b, result;
... // a and b are set
if(a && b)
    result = functionFour();
else if(b)
    result = functionTwo();
else if(a)
    result = functionThree();
else
    result = functionOne();

Explanation: If not both a and b are true, one must be false. In that case, if b is true, a must be false so there is no need to evaluate it redundantly.

Upvotes: 2

Related Questions