
"Konstantin Echenko" <clean@pisem.net> wrote in message news:cjovcj$oq$1@sea.gmane.org...
Hi All. Some time ago Maxim Yegorushkin suggested use boost/bind to implement lazy ScopeGuard. I evolved this parasitic idea and reused a lot of code from boost/bind by preprocessing to implement make_guard binders. The ScopeGuard can be used as usual: scope_guard g = make_guard( func, args ); What do you think about it? Is it possible to "legalize" such approach?
In July I posted a minimalist scope_guard: http://groups.yahoo.com/group/boost/files/scope_guard.zip The point was not to include any machinery for binding arguments to functions, leaving that job instead to bind or lambda. It seems to have been mostly ignored on this list, but I use it in my recently accepted iostreams library, so it will be part of boost at least as an implementation detail. I'm hoping to work with Joaquin M Lopez Munoz, who uses a scope_guard in his multi_index library, to put some version of scope_guard in boost/detail. I'll repeat my announcement here: Jonathan Turkanis wrote:
I've uploaded a very simple version of Andrei and Petru's ScopeGuard to the files section: http://groups.yahoo.com/group/boost/files/scope_guard.zip.
It's only smart enough to handle cleanup functions or function objects with the signature 'void f()'; more complex cleanup is easy with Bind or Lambda.
There are two object generators: - make_guard returns a scope guard which propagates exceptions - safe_guard returns a scope guard which catches and ignores exceptions
Similarly, there are two macros - BOOST_SCOPE_GUARD declares an anonymous scope guard which propagates exceptions - BOOST_SAFE_GUARD declares an anonymous scope guard which catches and ignores exceptions
Best Regards, Jonathan
//------------------Example--------------------//
#include <iostream> #include <boost/bind.hpp> #include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <boost/scope_guard.hpp>
void goodbye() { std::cout << "goodbye\n"; }
void crash() { throw 0; }
struct T { void goodbye() { std::cout << "goodbye\n"; } };
// // Expected output: // hello // goodbye // goodbye // goodbye // goodbye // goodbye // int main() { using namespace boost;
T t;
// Scope guard which invokes t.goodbye(). scope_guard g1 = make_guard(boost::bind(&T::goodbye, t));
// Scope guard which invokes goodbye(). scope_guard g2 = make_guard(goodbye);
// Scope guard which executes std::cout << "goodbye\n". scope_guard g3 = make_guard( std::cout << boost::lambda::constant("goodbye\n") );
// Scope guard which invokes crash() in a try-catch block. scope_guard g4 = safe_guard(crash);
// Scope guard which invokes crash(). scope_guard g5 = make_guard(crash); g5.dismiss();
// Scope guard which invokes goodbye(). BOOST_SCOPE_GUARD(goodbye);
// Same. (Shows that generated variable names are working.) BOOST_SCOPE_GUARD(goodbye);
// Scope guard which invokes crash() in a try-catch block. BOOST_SAFE_GUARD(crash);
std::cout << "hello\n"; }