C++11: Generic Error Catcher

Guess what this is...
When working with legacy code in C++ we often have to deal with error handling via getError type interfaces. This also happens in JNI where C++ calling JVM methods should check the JVM exception status after the return.

A chap on G+ ask me if I could adapt my finally pattern to achieve this easily. He had already gotten a good solution using template specialization and forwarding methods - but it was a little complex. I have been on a client's site all day and am now knackered (very tired) so I got this working but am not sure it is strictly legal C++11. I will give it some more thought tomorrow.

The first rick here is that returning the result of an expression which returns void is legal (I think - see above):

e.g.
void doVoid();
void dog(){
return doVoid();
}


The next trick is that we can use the destructor of an object to cause the error handling (not exception handling) code to run after our return statement.

The BIGGEST trick is that we wrap our expression in a try/catch(...) to stop stack unwinding throws further down the stack causing a throw in a throw because we are likely to throw in a destructor. If we do not do this, we would get a throw in a throw and std::terminate would be called.

#include "stdafx.h"
#include <iostream>
#include <functional>
using namespace std;

void doVoid(){
  cout << "Doing void" << endl;
}

int doInt(){
  cout << "Doing int" << endl;
  return 1;
}

class doCommon{
public:
  explicit doCommon(){
    cout << "Creating common" << endl;
  }
  ~doCommon(){
    cout << "Doing common" << endl;
  }
};

#define GLERROR(expr) [&]{\
    doCommon __common_doer;\
    try{\
      return expr;\
    }catch(...){/* set some error thing here */} \
  }()

int _tmain(int argc, _TCHAR* argv[])
{
  int what=GLERROR(doInt());
  GLERROR(doVoid());
  cout << "Got " << what << endl;
  return 0;
}


Naturally, because we are using a closure with [&] semantics, the macro will work just fine even though the code is running in a different scope to the one that the program source code intent would imply.

The proof of the pudding is in the output:

Creating common
Doing int
Doing common
Creating common
Doing void
Doing common
Got 1

But seriously - I am not sure this is a good pattern; is was fun trying to work it out.

Good night all - AJ