3

I have several steps in a function, if a step fails, I don't want to execute the following steps. I also would like to only have one return statement. one option is nested if-else but that gets nasty so I won't even put an example here.

What I've been doing is something like this (assume step_n functions return bool):

bool my_function()
{
   bool succeeded;

   succeeded = step_1();

   if(succeeded)
   {
      succeeded = step_2();
   }

   if(succeeded)
   {
      succeeded = step_3();
   }

   ...

   if(succeeded)
   {
      succeeded = step_n();
   }

   return succeeded;
}

This seems like the best case I can think of, but when the function does not return bool and I have to do an additional check each function call, things can get very repetitive and ugly.

Any modern c++ ways to accomplish this same idea?

cam.b
  • 127
  • 9
  • 2
    Use exceptions. Only catch an exceptions if the code can recover from them. This approach leave above the code looking like `step_1(); step_2(); step_3(); ... step_n();` No `if` tests and no need to return a result. Every function either works or throws. – Richard Critten Mar 17 '23 at 23:48
  • 1
    @RichardCritten using exceptions for non errror conditions, especially to control program flow, is a classic anti patern – pm100 Mar 18 '23 at 00:02
  • @pm100 I think I misunderstood the question. If `step_x()` fails I read this as being an error condition. – Richard Critten Mar 18 '23 at 00:05
  • If failure typically doesn't occur when the program operates normally, it should be reported as exception. This is entirely depending on the use case, e. g. a disk failure is exceptional for regular programs, but can be considered the normal case for a disk repair program. – zett42 Mar 18 '23 at 08:16
  • In my case, a failed step would indicate an "error condition". This was not in my original post, but this is in an environment where we are not using typical exceptions for error handling, but this does seem like the most logical approach in that case. Thanks! – cam.b Mar 20 '23 at 19:15

3 Answers3

7

This code is equivalent to what you show.

bool my_function()
{
   return step_1() &&
          step_2() &&
          step_3() &&
   ... 
          step_n();
}

It's not "modern" though. Any version of C++ can do this.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • Love it, this has the simplicity I need. For other's looking here. [`&&` execution is guaranteed left-to-right](https://stackoverflow.com/questions/5683026/logical-and-or-is-left-to-right-evaluation-guaranteed), which is why this works. The only downfall would be if more than one statement was needed in each `if` block. But that was not a part of my original question. – cam.b Mar 20 '23 at 19:19
  • 1
    @cam.b if more than one statement were needed in a single condition, put the statements in a lambda that returns the appropriate `bool`. – Drew Dormann Mar 20 '23 at 19:28
  • great idea! That would do it for me then. – cam.b Mar 20 '23 at 20:09
2

(puts on fire protective clothing)

  bool func(){
     bool success = false; 
     if(!func1()) goto out;
     if(!func2()) goto out;
     if(!func3()) goto out;
     success = true;
    out:
     return success;
   }
pm100
  • 48,078
  • 23
  • 82
  • 145
1

This is going to be memory-inefficient, but not very error prone:

auto const steps =
std::to_array<std::function<bool()>({
    [&]{/*TODO:step_1 instructions*/},
    [&]{/*TODO:step_2 instructions*/},
    //TODO: more steps...
    [&]{/*TODO:step_n instructions*/}
});

for(auto const& f:steps)
    if (!f());
       break;

You can also use std::find_if - instead of raw for loop - to count the executed steps:

auto step_count=distance(
     begin(steps),
     std::find_if(
          begin(steps),
          end(steps),
          [](auto const & f)/*->bool*/
            {return !f();}));

required std header files are:

#include <array>
#include <iterator>
#include <algorithm>
#include <functional>
Red.Wave
  • 2,790
  • 11
  • 17