Boost logo

Boost :

From: Hans Larsen (hans_at_[hidden])
Date: 2007-03-30 18:48:59


Hi,

You've probably seen "modern" languages that incorporate the keyword
finally, but nothing such exists in C++. I've come with a simple
class that could perform close to that keyword. The main exception is
that you have to define what finally does BEFORE the try catch
clause, which is kind of counter-intuitive but not hurtful.

The obvious advantages of such a class over a smart_ptr<X> (X could
be void*) is that you can use Boost.Bind (cf my code sample), and the
order of the instructions in the finally "clause" is predictable
(which is IIRC not guaranteed on destruction of variables).
Obviously, though, one could not throw inside a finally...

Is such a concept existent currently in Boost (or any library)? If
not, would it be useful? I think so, but eh could be wrong :)

Hans Larsen

----------------
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

class finally {
protected:
        struct helper_base_t { virtual ~helper_base_t() {} };
        template< class T > struct helper_t : public helper_base_t {
                const T& _;
                helper_t( const T& t ) : _(t) { }
                ~helper_t() { _(); }
        };
        std::vector< helper_base_t* > vec;
        
public:
        finally() {}
        ~finally() {
                for( std::vector<helper_base_t*>::iterator it = vec.begin(); it !=
vec.end(); it++ )
                        delete (*it);
        }
        
        template< class T > void operator()( const T& t ) {
                vec.push_back( new helper_t<T>(t) );
        }
};

struct func1 {
        void operator()() const { std::cout << 1 << std::endl; }
};

void func2( int& x ) {
        std::cout << x << std::endl;
        x++;
}

void function()
{
        using namespace boost;
        using boost::lambda::var;
        
        finally f;
        int x = 0;
        
        f( func1() ); // Simply print 1
        // This way we can pass parameters between calls...
        f( bind( func2, ref(x) ) ); // using Boost.Bind, modify x - will
print 0.
        f( bind( func2, ref(x) ) ); // using Boost.Bind, modify x - will
print 1
        f( var(x) = 5 ); // using Boost.Bind && Boost.Lambda
        f( bind( func2, ref(x) ) ); // using Boost.Bind, modify x - will
print 5
        
        try {
                throw int(5);
        } catch( short x ) {
                std::cout << (x+1) << std::endl;
        }
}

int main()
{
        try {
                function();
        }
        catch( int x )
        {
                std::cout << x << std::endl;
        }
        return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk