8

There are times where I want to be sure that some function call is executed before returning from an other function, or an integer is decremented.

For example consider this code:

void doSomething()
{
    try
    {
        .....
        .....
        return;
        .....
        .....
        .....
        return;
        ......
    } catch ( ... )
    }
    myvariable--;
}

I want to be sure that myvariable is always decremented, no mater if there is an exception, or a return call. Is there any build in object in C++ for this, or I should create my own class that accepts an std::function and executes it when the object gets out of scope at the object destructor?

For example, in C# there is the try..catch...finally block where in finally you can put any code you want to execute before returning from the function.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Yiannis Mpourkelis
  • 1,366
  • 1
  • 15
  • 34

5 Answers5

6

You can write your own, class, that performs some action, in its destructor.

class DoAction
    {
public:
    DoAction (std::function<void ()> func) : m_func (func)
        {
        }
    ~DoAction ()
        {
        m_func ();
        }

private:
    std::function<void ()> m_func;
    };

And then, create an object of it, in a following way:

DoAction action([&] {/*Code that you want to be executed upon leaving the scope.*/});

Live demo.

Algirdas Preidžius
  • 1,769
  • 3
  • 14
  • 17
4

I often use std::unique_ptr for this, using lambda as custom deleter. It's slightly awkward, since you have to do decltype() for deleter type, but other than that, it saves you writing a 10-liner class.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
2

You can do something like this:

#include <iostream>
template <typename T>
struct decrementer_raii
{
   T& var;
   decrementer_raii(T& v) : var(v) {}
   ~decrementer_raii() { --var; }
};

int main()
{
    int x = 1;
    {
       decrementer_raii<int> dec(x);
    }
    std::cout << x;  // should print 0.
}

Live Example

or more like your scenario:

#include <iostream>
template <typename T>
struct decrementer_raii
{
   T& var;
   decrementer_raii(T& v) : var(v) {}
   ~decrementer_raii() { --var; }
};

void foo(int& x)
{
   decrementer_raii<int> dec(x);
   std::cout << x << "\n"; // x is still the original value passed-in (14)
   for (int i = 0; i < 10; ++i )
   {
      if ( i == 4 ) throw 10;  // force a throw 
   }
}

int main()
{
    int x = 14;
    try {
        foo(x);
    }
    catch(...) {}
    std::cout << x;  // should print 13.
}

Live Example 2

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
1

Your suggested solution of writing a simple wrapper class should work just fine. As far as I know there is no 'built-in' way of doing this in C++.

I wrote a simple class called Finally that does just what you wanted, calls a stored function as soon as it goes out of scope.

#include <functional>
#include <iostream>
#include <stdexcept>

class Finally
{
public:
    explicit Finally(std::function<void()> func);
    ~Finally();
private:
    std::function<void()> func;
};

Finally::Finally(std::function<void()> func)
    : func(func)
{}

Finally::~Finally()
{
    func();
}

void CallOnException()
{
    std::cout << "Function was called!" << std::endl;
}

void Run()
{
    const Finally finally(CallOnException);

    std::cout << "Throwing exception now!" << std::endl;
    throw std::runtime_error("Runtime error");

    std::cout << "This code will not be run." << std::endl;
}

int main()
{
    try
    {
        Run();
    }
    catch(...)
    {
        /* Handle exceptions */
    }

    return 0;
}

The output of this simple program is:

Throwing exception now!
Function was called!
JonatanE
  • 941
  • 7
  • 19
0

You have to write a class that calls a function or uses a lambda etc in its destructor.

Here's one called OnLeavingScope.

Nick Westgate
  • 3,088
  • 2
  • 34
  • 41