C++11: Try/Catch/Finally Pattern Using RAII & Lambdas

Looking at things a bit differently.
Copyright: Dr Alexander J Turner all rights reserved
I totally agree with Stroustrup's assertion that RAII is a better pattern than Try/Catch/Finally for resource management. Nevertheless, there are other things we might want to use finally for than just cleaning up resource. Here I show a very simple, clean and minimalist pattern for achieving finally clauses in C++11.

In Java and C# development finally can be really handy for instrumentation during debugging or over key areas for logging. The key to my pattern is to use RAII semantics to cause a closure to be run when a 'finally' object goes out of scope. This means that we can absolutely guarantee that the closure will be executed because the compiler guarantees to run the destructors of all auto variables when they go out of scope.

Here I am going to show the pattern being used to help debug a bit of poorly written code. I have deliberately written code with poor exception safety. I am pretending that have been given this code and am trying to work out what has gone wrong. Honestly, it is simple enough that one should be able to eye ball it and see the problem - but if I made it too complex it would not be a good example.

How It Works:
We have a very simple class:


class finally{
  private:
    function<void()> finallyClause;
        finally(const finally &);
        finally& operator=(const finally &);
  public:
    explicit finally(function<void()> f) : finallyClause(f){}

    ~finally(){
      finallyClause();
    }
  };


This is like any other RAII class except that it is not for resource management. What it does is store a closure away and then invoke that closure then it is destroyed. We have to make a copy (default copy constructor) of the closure because otherwise it might have been destroyed by the time we get to it (as I found out the hard way).
We use finally like this:

finally f([&]{
        if(x>0){
          cout << "Error allocating precious things, failed to allocate " << x << " instances." << endl;
        }
      });


A piece of code like this is put before and in the same scope as that after which it must run. The wonderful thing about this pattern is that we close around all the local storage of the scope. The finally clause runs as though it is in-line with the rest of the code. The other thing which made me happy when I came up with this was that the finally clause has physically locality to the rest of the code in the source which make comprehension easier than having the code scattered around.

The Full Example:

// Finally.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <atomic>
#include <string>
#include <vector>
#include <functional>
#include <sstream>
using namespace std;

namespace nerdscentral{

  #define MAX_PRECIOUS_THINGS 20

  class finally{
  private:
    function<void()> finallyClause;
        finally(const finally &);
        finally& operator=(const finally &);
  public:
    explicit finally(function<void()> f) : finallyClause(f){}

    ~finally(){
      finallyClause();
    }
  };

  class preciousThing
  {
  private:
    std::atomic<long> totalCount;
  public:
    preciousThing() : totalCount(0){}
    string getAPreciousThing(){
      ++totalCount;
      if(totalCount>MAX_PRECIOUS_THINGS) throw ("No more precious things");
      auto os = stringstream("A precious thing number: ");
      os << totalCount;
      cout << "Created precious thing: " << os.str() << endl;
      return os.str();
    }
  };

  preciousThing preciousThingProvider;

  class demoFinally{
  private:
    long nThingsUsed;

  public:
    demoFinally()
      : nThingsUsed(0){
      cout << "demoFinally " << this << " has been constructed" << endl;
    }

    vector<string> getPreciousThings(int x){
      // Added to help instrument / debug the code
      finally f([&]{
        if(x>0){
          cout << "Error allocating precious things, failed to allocate " << x << " instances." << endl;
        }
      });
      nThingsUsed+=x;
      vector<string> ret(x);
      for(;x>0;--x) ret.insert(ret.end(),preciousThingProvider.getAPreciousThing());
      auto dog=[]{};
      return ret;
    }
  };
}

int _tmain(int argc, _TCHAR* argv[])
{
  auto d = nerdscentral::demoFinally();
  try{
    d.getPreciousThings(22);
  }catch(...){
    cout << "Something went hideously wrong - but I have no idea what!" << endl;
  }
  return 0;
}


Its Output:
I retouched this listing to highlight the output from the finally clause.

demoFinally 003AFBF8 has been constructed
Created precious thing: 1 precious thing number:
Created precious thing: 2 precious thing number:
Created precious thing: 3 precious thing number:
Created precious thing: 4 precious thing number:
Created precious thing: 5 precious thing number:
Created precious thing: 6 precious thing number:
Created precious thing: 7 precious thing number:
Created precious thing: 8 precious thing number:
Created precious thing: 9 precious thing number:
Created precious thing: 10precious thing number:
Created precious thing: 11precious thing number:
Created precious thing: 12precious thing number:
Created precious thing: 13precious thing number:
Created precious thing: 14precious thing number:
Created precious thing: 15precious thing number:
Created precious thing: 16precious thing number:
Created precious thing: 17precious thing number:
Created precious thing: 18precious thing number:
Created precious thing: 19precious thing number:
Created precious thing: 20precious thing number:
Error allocating precious things, failed to allocate 2 instances.
Something went hideously wrong - but I have no idea what!


Some Alternative Uses Of The Pattern:
I am not sure these are exactly good ideas, but:

  1. It did occur to me that this patter would work for rapid escaping from deeply nested loops. Just return out of the innermost loop and hand over processing the the finally clause. That pattern fits into the scheme notion of replacing 'goto' with lambdas (sorry for saying that word - urrg shiver).
  2. It also occurs to me that we can nest finally clauses inside finally clauses.


Anyone have any other patters based on this approach? I'd love to hear them.