Quantcast
Viewing all articles
Browse latest Browse all 17

Answer by anton_rh for Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?)

Another "finally" block emulation using C++11 lambda functions

template <typename TCode, typename TFinallyCode>inline void with_finally(const TCode &code, const TFinallyCode &finally_code){    try    {        code();    }    catch (...)    {        try        {            finally_code();        }        catch (...) // Maybe stupid check that finally_code mustn't throw.        {            std::terminate();        }        throw;    }    finally_code();}

Let's hope the compiler will optimize the code above.

Now we can write code like this:

with_finally(    [&]()    {        try        {            // Doing some stuff that may throw an exception        }        catch (const exception1 &)        {            // Handling first class of exceptions        }        catch (const exception2 &)        {            // Handling another class of exceptions        }        // Some classes of exceptions can be still unhandled    },    [&]() // finally    {        // This code will be executed in all three cases:        //   1) exception was not thrown at all        //   2) exception was handled by one of the "catch" blocks above        //   3) exception was not handled by any of the "catch" block above    });

If you wish you can wrap this idiom into "try - finally" macros:

// Please never throw exception below. It is needed to avoid a compilation error// in the case when we use "begin_try ... finally" without any "catch" block.class never_thrown_exception {};#define begin_try    with_finally([&](){ try#define finally      catch(never_thrown_exception){throw;} },[&]()#define end_try      ) // sorry for "pascalish" style :(

Now "finally" block is available in C++11:

begin_try{    // A code that may throw}catch (const some_exception &){    // Handling some exceptions}finally{    // A code that is always executed}end_try; // Sorry again for this ugly thing

Personally I don't like the "macro" version of "finally" idiom and would prefer to use pure "with_finally" function even though a syntax is more bulky in that case.

You can test the code above here: http://coliru.stacked-crooked.com/a/1d88f64cb27b3813

PS

If you need a finally block in your code, then scoped guards or ON_FINALLY/ON_EXCEPTION macros will probably better fit your needs.

Here is short example of usage ON_FINALLY/ON_EXCEPTION:

void function(std::vector<const char*> &vector){    int *arr1 = (int*)malloc(800*sizeof(int));    if (!arr1) { throw "cannot malloc arr1"; }    ON_FINALLY({ free(arr1); });    int *arr2 = (int*)malloc(900*sizeof(int));    if (!arr2) { throw "cannot malloc arr2"; }    ON_FINALLY({ free(arr2); });    vector.push_back("good");    ON_EXCEPTION({ vector.pop_back(); });    ...

Viewing all articles
Browse latest Browse all 17

Trending Articles