Reputation: 572
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
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
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
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
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
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