Get your RAII on with the finally template class

March 31, 2009

C++'s destructors are great for ensuring that resources get cleaned up at the end of a scope, but writing wrapper classes for every damn C library type you use gets tired real quick. Slava suggested that I write a template class to do it once, so guess what? I did.

template<typename T>
struct finally {
    typedef T value_type;
    typedef boost::function<void (T)> destructor_type;

    T object;
    destructor_type destructor;

    finally(T o, destructor_type d) : object(o), destructor(d) {}
    ~finally() { destructor(object); }
};

With finally in your toolbox, whenever you need to toss a fopen, malloc, or other C resource acquisition in, you don't need to give up exception safety anymore!

{
    FILE *f = fopen("foo", "r");
    finally<FILE*> close_f(f, fclose);
}

{
    void *buf = malloc(17);
    finally<void*> free_buf(buf, free);
}

{
    PGconn *conn = PQconnectdb(conninfo);
    finally<PGconn*> finish_conn(conn, PQfinish);
}

Because finally uses boost::function to hold the destructor function, it works with functor objects and functions that don't return void.

UPDATE: kefex on reddit points out that boost::shared_ptr does this already:

boost::shared_ptr<FILE> pf(fopen("foo", "r"), fclose);