Nested redundant 'if' conditions - c++

Is there a better (or cleaner) way to write the following code?
if(conditionX)
{
if(condition1)
{
// code X1
}
else if(condition2)
{
// code X2
}
}
else if(conditionY)
{
if(condition1)
{
// code Y1
}
else if(condition2)
{
// code Y2
}
}
I have a few more conditions, but I guess you get the point.

There are four approaches to this problem, none of which is universal:
Leave everything as is - There isn't much code duplication here. If computing condition1 and condition2 is tricky, compute them upfront and store them in bool variables
Make conditionX and conditionY produce a result that lets you unify condition1 and condition2 - This is not always possible, but in some situations you could prepare a variable that unifies the activities taken in the two branches, say, by using a function pointer or a lambda.
Put the processing logic into subclasses with virtual functions to eliminate conditional logic - This is possible only when your initial design missed an opportunity to subclass. Essentially, this approach pushes the decision on conditionX/conditionY into a place where a subclass is created, and then "reuses" that decision later on by calling a proper override of a virtual function in the interface.
Create a numeric combination representing all three conditions, and convert to switch - This trick unifies the conditionals, reducing the nesting.
Here is an example of the last approach:
int caseNumber = ((conditionX?1:0) << 3)
| ((conditionY?1:0) << 2)
| ((condition2?1:0) << 1)
| ((condition1?1:0) << 0);
switch (caseNumber) {
case 0x09:
case 0x0D:
case 0x0F: // code X1
break;
case 0x0A:
case 0x0E: // code X2
break;
case 0x05:
case 0x07: // code Y1
break;
case 0x06: // code Y2
break;
}

If your concern is with clean code in terms of viewing the source, my advice would be to segregate the blocks into their own sections, something like:
if (conditionX) processConditionX();
else if (conditionY) processConditionY();
and so on.
Then, in the sub-functions, you place the "meat":
void processConditionX (void) {
if(condition1) {
// code X1
} else if(condition2) {
// code X2
}
}
You can modify it to pass in and return parameters as necessary and I'd make the conditions and function names a little more descriptive, though I assume they're just examples here.

You can implement a state-machine instead:
#define COMBINATION(a,b,c,d) (((a)<<3)|((b)<<2)|((c)<<1)|((d)<<0))
switch (COMBINATION(conditionX,conditionY,condition1,condition2))
{
case COMBINATION(0,0,0,0): break;
case COMBINATION(0,0,0,1): break;
case COMBINATION(0,0,1,0): break;
case COMBINATION(0,0,1,1): break;
case COMBINATION(0,1,0,0): break;
case COMBINATION(0,1,0,1): CodeY2(); break;
case COMBINATION(0,1,1,0): CodeY1(); break;
case COMBINATION(0,1,1,1): CodeY1(); break;
case COMBINATION(1,0,0,0): break;
case COMBINATION(1,0,0,1): CodeX2(); break;
case COMBINATION(1,0,1,0): CodeX1(); break;
case COMBINATION(1,0,1,1): CodeX1(); break;
case COMBINATION(1,1,0,0): break;
case COMBINATION(1,1,0,1): CodeX2(); break;
case COMBINATION(1,1,1,0): CodeX1(); break;
case COMBINATION(1,1,1,1): CodeX1(); break;
}
This includes only one branch operation, so it is possibly a little more efficient (even though it also includes an additional runtime computation (at the switch line)).
As to being cleaner, I guess it's a matter of perspective, but the template above also gives you a convenient way to detect all unhandled branches within your code.
Please note that if any of the condition variables may have a value other than 1 or 0, then you should:
#define COMBINATION(a,b,c,d) (((a)?8:0)|((b)?4:0)|((c)?2:0)|((d)?1:0))
Update (attributed to #Jonathan Wakely in one of the comments below):
If you're using C++11, then you may replace the COMBINATION macro with a constexpr function:
constexpr int COMBINATION(bool a,bool b,bool c,bool d)
{
return ((int)a<<3) | ((int)b<<2) | ((int)c<<1) | ((int)d<<0);
}

I would provide the decision inside the first if as a parameter to a separated functions which then decides which code to execute, like:
if(conditionX)
{
Method1(Condition Parameters)
}
else if(conditionY)
{
Method1(Condition Parameters)
}
Another way would be to provide all needed info to a decision method (matrix), this method returns an integer which you use in a switch statement to decide which code to execute. In this way you separate the desicion logic which makes it readable and easy to unittest if needed:
DecisionMatrix(conditionX, conditionY, condition1, condition2)
{
// return a value according to the conditions for Example:
// CoditionX + Condition1 => return 1
// CoditionX + Condition2 => return 2
// CoditionY + Condition1 => return 3
// CoditionY + Condition2 => return 4
}
switch(DecisionMatrix)
{
case 1: //run code X1
break;
case 2: //run code X2
break;
case 3: //run code Y1
break;
case 4: //run code Y2
break;
}

The best way here would be to use polymorphism (Only if the chunks of code are huge)
If they are small code snippets, creating classes would obviously be an overkill.
Therefore, if there is similarity in all codes, I'd suggest a seemingly easy but really difficult task.
Try to parametrize them as much as you can.
Create a function that takes those and call them in the conditions
Now the code would be in function blocks and "cleaner"
It is always difficult to create simple things.
if (conditionX) {
method(parameterX);
else if (conditionY) {
method(parameterY);
}
where
void method(ParameterType e) {
if (condition 1) {
// Code in terms of parameter e
} else if (condition2) {
// Code in terms of parameter e
}
}
The condition that you can parametrize should be kept outside.
Hope this helps.

I think this way can be another way for solving your code.
enum ConditionParentType
{
CONDITION_NONE = 0,
CONDITION_X,
CONDITION_Y,
};
enum ConditionChildType
{
CONDITION_0 = 0,
CONDITION_1,
CONDITION_2,
};
class ConditionHandler
{
public:
explicit ConditionHandler(ConditionParentType p_type, ConditionChildType c_type)
: p_type_(p_type), c_type_(c_type) {};
void DoAction()
{
if(child_type == CONDITION_1)
{
}
else if(child_type == CONDITION_2)
{
}
else
{
//error
}
}
private:
const ConditionParentType p_type_;
const ConditionChildType c_type_;
};
int main(int argc, char *argv[])
{
ConditionParentType parent_type = GetParentType();
ConditionChildType child_type = GetChildType();
ConditionHandler handler(parent_type, child_type);
handler.DoAction();
getchar();
return 0;
}

If the combination of conditions means something then I'd write a set simple methods that return boolean values. You would end up with something like:
if (first-condition(conditionX, condition1)) {
// code X1
} else if (first-condition(conditionX, condition2)) {
// code X2
} else if (third-condition(conditionY, condition1)) {
// code Y1
} else if (fourth-condition(conditionY, condition2)) {
// code Y2
}
The names of the methods describe the conditions. Don't worry that the methods are only called once (the compiler will probably in-line them anyway), the important bit it that your code then becomes self documenting.

I'm quite surprised by the other suggested answers, which are mostly wrong if:
The two repeated conditions condition1 or condition2 are complex, in which case DRY comes into play, or
Any of the four conditions have side effects, or
Any of the conditions are slow (for example, find the minimum of a large array, or read a file), or
A boolean short-circuit is needed, as in: if (p == 0) {...} else if (p->foo == 42) {...}.
If none of these hold, as is the case 99.42% of the time, then leave the code as it is. Or, as a minor variation, change it so the nesting (that is, indentation) is only one level, not two.
Otherwise, you will need to use temporary variables as follows
const bool tstX = (conditionX);
const bool tstY = tstX || (conditionY);
const bool tst1 = tstY && (condition1);
const bool tst2 = tstY && !tst1 && (condition2);

the original code doesn't look to bad. Depending on the specific case it may or may not be more readable to do something like:
if(conditionX and condition1) {
// code X1
}
else if(conditionX and condition2) {
// code X2
}
else if(conditionY and condition1) {
// code Y1
}
else if(conditionY and condition2)
// code Y2
}

Related

How to replace the 'break'?

In my program I have a structure similar to the following one:
while (true) {
int c;
cout << "Type a command: ";
cin >> command;
switch (c) {
case 1:
// [...]
if (!condition) break;
// [...]
if (!condition2) break;
// [...]
if (!condition3) break;
// [...]
break;
case 2:
// [...]
break;
default:
break;
}
}
But our professor told us to never use the break except in the switch case to exit... I was wondering if there's a better and smarter way to replace the block if(!condition) break;.
My main goal is to prevent the program from doing certain actions if condition is not verified.
In order to avoid break you need to use the opposite condition, and instead of breaking the flow, control it:
switch (c) {
case 1:
// [...]
if (condition) {
// [...]
if (condition2) {
// [...]
if (condition3) {
// [...]
} // if the third condition is false, you will continue to the break.
} // if the second condition is false, you will continue to the break.
} // if the first condition is false, you will continue to the break.
break;
// ...
}
EDIT
To avoid complex conditions, you can use functions:
void condition_1_actions();
void condition_2_actions();
void condition_3_actions();
// ... main ...
case 1:
if (condition) condition_1_actions();
break;
// ... After main ...
condition_1_actions() {
// do some actions
// Calculate condition2 or pass it as parameter
if (condition2) condition_2_actions();
}
condition_2_actions() {
// do some actions
// Calculate condition3 or pass it as parameter
if (condition3) condition_3_actions();
}
condition_3_actions() {
// do some actions
}
I'm sure that "your professor" would agree: "if it ain't broke, don't fix it."
The logic as-written is clear, and I presume that it works. Also, as-written it would be maintainable: I wouldn't have to radically change the source-code if when I needed to add a new condition to it. Just leave it alone. Anything that you hear from a professor – or anyone else – is a guideline!
"Clarity" is always key, because as years go by your source-code is going to be added-to by many others. I like the original idiom because each of the cases is clearly distinct: "make this test, and then bail-out." (Could be break or return depending on the situation.) It's very easy to see how the logic goes, and it's equally easy to add another case to it "in the same vein."
In the end – "it makes absolutely no difference to the digital computer." (As Perl programmers like to say, "there's more than one way to do it.™") But it might be attractive to your [future ...] colleagues. There are no absolutes here. Just try to be nice to them. Be "stupid-obvious."

Using switch case for bitwise enums

I have implemented my own typesafe bitwise enum operators following this article: http://blog.bitwigglers.org/using-enum-classes-as-type-safe-bitmasks/
Here is the enum I am talking about:
enum class OutputStream : unsigned int
{
None = 0,
// Using bitshift operator (always one bit set to 1)
Console = 1 << 0,
File = 1 << 1,
Other = 1 << 2
};
In case you wonder, it's for a logging function.
Problem:
I want to use the enum in a switch statement such as
switch(stream)
{
case OutputStream::Console:
//Do this
case OutputStream::File:
//Do that
default:
break;
}
Note that there shouldn't be a break; in between the case statements since more than one case can be true.
However, this doesn't seem to work. More precisely, when I use OutputStream::Console | OutputStream::File neither case is executed.
My only solution to this problem was this awkward looking if statement:
if((stream & OutputStream::Console) != OutputStream::None) { /*Do this*/ }
if((stream & OutputStream::File) != OutputStream::None) { /*Do that*/ }
But for me, this defeats the point of a need enum based solution. What am I doing wrong?
As other said in comments, switch is not the best way, but it is still possible to do:
for (int bit = 1; bit <= (int) OutputStream::LAST; bit <<= 1)
{
switch((OutputStream) (bit & stream))
{
case OutputStream::Console:
//Do this
break;
case OutputStream::File:
//Do that
break;
// etc...
// no default case no case 0!
}
}
So basically you will iterate over all individual bits, for each test if it is present in the stream variable and jump to the appropriate case, or jump nowhere if it is 0.
But in my opinion the individual ifs are better. At least you have better control over in which order are the bits evaluated.

How to use case condition in switch as variable in c++? [duplicate]

This question already has answers here:
C++ Switch won't compile with externally defined variable used as case
(8 answers)
Closed 6 years ago.
Here x, y, z are integers but those are not known at start. During the running it will calculate the values of x, y, z. I want to use those values as case condition.
Is there any way to use those values in switch?
Instead of switch if I use if else loop, ho
id = 1;
switch(id){
case x:
//call some function
break;
case y:
//call some different function
break;
default:
//error
break;
}
No, the case labels need to be compile-time integral constants.
You will need to use conditional statements instead:
if (id == x) {
// ...
} else if (id == y) {
// ...
} else if (id == z) {
// ...
} else {
// "default case"
}
Consider also that x, y and z may not all be distinct, so the order of the statements matters. (But the order also matters for case labels in a switch if you fall through any of them.)
What you want is not supported (as pointed out by other answers). However, worse, it is not sensible and hence cannot be emulated in any way. This is because the cases in a switch are unique and their order insignificant (except in case of fall-through), so
switch(enum_object) {
case A: return foo<A>();
case B: return foo<B>();
default: return foo<C>();
}
and
switch(enum_object) {
default: return foo<C>();
case B: return foo<B>();
case A: return foo<A>();
}
gives the same code, but
if(id == run_time_value_A)
return foo<A>();
if(id == run_time_value_B)
return foo<B>();
return foo<C>();
is not the same as, say,
if(id == run_time_value_B)
return foo<B>();
if(id == run_time_value_A)
return foo<A>();
return foo<C>();
they differ if run_time_value_B==run_time_value_A.
As pointed out by n.m, Kerrek SB, and this SO answer, case labels need to be compile-time integral constants.
The answer of Kerrek SB shows the immediate and intuitive if - else if-cascade solution.
However, if you'd also like to make use of the break-functionality in switch-statements, then the following if - if - cascade as general pattern would apply:
bool isBreak = false;
if (id==x) {
...
isBreak = true;
}
if (!isBreak && id==y) {
...
}
if (!isBreak) {
...
}
Note that with this pattern you can express - in contrast to switch- also situations where more than one of the case-statements (denoted as ifs) match, as, e.g. when x == y.

Does case-switch work like this?

I came across a case-switch piece of code today and was a bit surprised to see how it worked. The code was:
switch (blah)
{
case a:
break;
case b:
break;
case c:
case d:
case e:
{
/* code here */
}
break;
default :
return;
}
To my surprise in the scenario where the variable was c, the path went inside the "code here" segment. I agree there is no break at the end of the c part of the case switch, but I would have imagined it to go through default instead. When you land at a case blah: line, doesn't it check if your current value matches the particular case and only then let you in the specific segment? Otherwise what's the point of having a case?
This is called case fall-through, and is a desirable behavior. It allows you to share code between cases.
An example of how to use case fall-through behavior:
switch(blah)
{
case a:
function1();
case b:
function2();
case c:
function3();
break;
default:
break;
}
If you enter the switch when blah == a, then you will execute function1(), function2(), and function3().
If you don't want to have this behavior, you can opt out of it by including break statements.
switch(blah)
{
case a:
function1();
break;
case b:
function2();
break;
case c:
function3();
break;
default:
break;
}
The way a switch statement works is that it will (more or less) execute a goto to jump to your case label, and keep running from that point. When the execution hits a break, it leaves the switch block.
That is the correct behavior, and it is referred to as "falling through". This lets you have multiple cases handled by the same code. In advanced situations, you may want to perform some code in one case, then fall through to another case.
Contrived example:
switch(command)
{
case CMD_SAVEAS:
{
this->PromptForFilename();
} // DO NOT BREAK, we still want to save
case CMD_SAVE:
{
this->Save();
} break;
case CMD_CLOSE:
{
this->Close();
} break;
default:
break;
}
This is called a fall-through.
It is exactly doing what you are seeing: several cases is going to execute same piece of code.
It is also convenient in doing extra processing for certain case, and some shared logic:
// psuedo code:
void stopServer() {
switch (serverStatus)
case STARTING:
{
extraCleanUpForStartingServer();
// fall-thru
}
case STARTED:
{
deallocateResources();
serverStatus = STOPPED;
break;
}
case STOPPING:
case STOPPED:
default:
// ignored
break;
}
This is a typical use of fall-through in switch-case. In case of STARTING and STARTED, we need to do deallocateResources and change the status to STOPPED, but STARTING need some extra cleanup. By the above way, you can clearly present the 'common logic' plus extra logic in STARTING.
STOPPED, STOPPING and default are similar, all of them fall thru to default logic (which is ignoring).
It is not always a good way to code like this but if it is well used it can present the logic better.
Luckily for us, C++ doesn't depend on your imagination :-)
Think of the switch labels as "goto" labels, and the switch(blah) simply "goes to" the corresponding label, and then the code just flows from there.
Actually the switch statement works the way you observed. It is designed so that you can combine several cases together until a break is encountered and it acts something like a sieve.
Here is a real-world example from one of my projects:
struct keystore_entry *new_keystore(p_rsd_t rsd, enum keystore_entry_type type, const void *value, size_t size) {
struct keystore_entry *e;
e = rsd_malloc(rsd, sizeof(struct keystore_entry));
if ( !e )
return NULL;
e->type = type;
switch (e->type) {
case KE_DOUBLE:
memcpy(&e->dblval, value, sizeof(double));
break;
case KE_INTEGER:
memcpy(&e->intval, value, sizeof(int));
break;
/* NOTICE HERE */
case KE_STRING:
if ( size == 0 ) {
/* calculate the size if it's zero */
size = strlen((const char *)value);
}
case KE_VOIDPTR:
e->ptr = rsd_malloc(rsd, size);
e->size = size;
memcpy(e->ptr, value, size);
break;
/* TO HERE */
default:
return NULL;
}
return e;
}
The code for KE_STRING and KE_VOIDPTR cases is identical except for the calculation of size in case of string.

How can this switch statement be simplified?

I have two switch statement on inside another.
Like this
switch(something)
{
case h:
switch(s)
{
case e:
break;
default:
}
break;
default:
}
Can i simplify it any way? Is there a way to use only one switch statement?
I thought of moving it to a different function but I'll need to pass a lot of variables.
It depends on what 'something' and 's' are.
Also, based on this switch statement. You could remove it completely and get the same results.
I don't think you need a break after the default, since there shouldn't be any skippable statements after it.
switch(something)
{
case h:
switch(s)
{
case e:
break;
default:
}
break;
default:
}
You could try indenting it more to make it more readable, but I don't see how you could do it with one switch
Without knowing what you are trying to accomplish with this logic we will not be able to siginificantly simplify this bit of code.
If the switch statements really are just checking for a single condition and then have default logic, this would probably be a little cleaner with if statements:
if (something == h)
{
if (s == e)
{
}
else
{
//default
}
}
else
{
//default
}
Maybe this is what you want?:
if((something == h) && (s == e))
{
// Do something
}