Assuming I have this pseudo-code:
bool conditionA = executeStepA();
if (conditionA){
bool conditionB = executeStepB();
if (conditionB){
bool conditionC = executeStepC();
if (conditionC){
...
}
}
}
executeThisFunctionInAnyCase();
Functions executeStepX
should be executed if and only if the previous succeed.
In any case, the executeThisFunctionInAnyCase
function should be called at the end.
I'm a newbie in programming, so sorry for the very basic question: is there a way (in C/C++ for example) to avoid that long if
chain producing that sort of "pyramid of code", at the expense of the code legibility?
I know that if we could skip the executeThisFunctionInAnyCase
function call, the code could be simplified as:
bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;
But the constraint is the executeThisFunctionInAnyCase
function call.
Could the break
statement be used in some way?
Assuming you don't need individual condition variables, inverting the tests and using the else-falthrough as the "ok" path would allow you do get a more vertical set of if/else statements:
Omitting the failed variable makes the code a bit too obscure IMO.
Declaring the variables inside is fine, no worry about = vs ==.
This is obscure, but compact:
Another approach -
do - while
loop, even though it was mentioned before there was no example of it which would show how it looks like:(Well there's already an answer with
while
loop butdo - while
loop does not redundantly check for true (at the start) but instead at the end xD (this can be skipped, though)).To improve on Mathieu's C++11 answer and avoid the runtime cost incurred through the use of
std::function
, I would suggest to use the followingThis simple template class will accept any functor that can be called without any parameters, and does so without any dynamic memory allocations and therefore better conforms to C++'s goal of abstraction without unnecessary overhead. The additional function template is there to simplify use by template parameter deduction (which is not available for class template parameters)
Usage example:
Just as Mathieu's answer this solution is fully exception safe, and
executeThisFunctionInAnyCase
will be called in all cases. ShouldexecuteThisFunctionInAnyCase
itself throw, destructors are implicitly markednoexcept
and therefore a call tostd::terminate
would be issued instead of causing an exception to be thrown during stack unwinding.Assuming the desired code is as I currently see it:
I would say that the correct approach, in that it's the simplest to read and easiest to maintain, would have fewer levels of indentation, which is (currently) the stated purpose of the question.
This avoids any need for
goto
s, exceptions, dummywhile
loops, or other difficult constructs and simply gets on with the simple job at hand.Have your execute functions throw an exception if they fail instead of returning false. Then your calling code could look like this:
Of course I'm assuming that in your original example the execution step would only return false in the case of an error occuring inside the step?
If your code is as simple as your example and your language supports short-circuit evaluations, you could try this:
If you are passing arguments to your functions and getting back other results so that your code cannot be written in the previous fashion, many of the other answers would be better suited to the problem.