// Copyright Alexander Nasonov 2005 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Acknowledge: Maxim Yegorushkin for the idea of in-place guard. #include #include #include #include extern void* _finally_last_params; // TODO: boost::thread_specific_ptr // Generate _finally_typeof_{__LINE__}{var} #define FINALLY_AUX_TYPE(var) \ BOOST_PP_CAT(_finally_typeof_, BOOST_PP_CAT(__LINE__,var)) #define FINALLY_AUX_DEREF(r,params,var) params -> var , #define FINALLY_AUX_TYPEDEF(r,_,var) typedef typeof(var) FINALLY_AUX_TYPE(var); #define FINALLY_AUX_SEMICOLON() ; #define FINALLY_AUX_REF(r,end,var) FINALLY_AUX_TYPE(var) & var end() #define FINALLY_BEGIN(seq) \ BOOST_PP_SEQ_FOR_EACH(FINALLY_AUX_TYPEDEF,_,seq) \ struct BOOST_PP_CAT(_finally_params_,__LINE__) { \ BOOST_PP_SEQ_FOR_EACH(FINALLY_AUX_REF,FINALLY_AUX_SEMICOLON,seq) \ } BOOST_PP_CAT(_finally_params_,__LINE__) = { BOOST_PP_SEQ_ENUM(seq) }; \ _finally_last_params = &BOOST_PP_CAT(_finally_params_,__LINE__); \ struct BOOST_PP_CAT(_finally_guard_,__LINE__) { \ void* _finally_params; \ BOOST_PP_CAT(~_finally_guard_,__LINE__)() { \ typedef struct BOOST_PP_CAT(_finally_params_,__LINE__) params; \ params* p= static_cast(_finally_params); \ _finally_body(BOOST_PP_SEQ_FOR_EACH(FINALLY_AUX_DEREF,p,seq) 0); \ } \ static void _finally_body( \ BOOST_PP_SEQ_FOR_EACH(FINALLY_AUX_REF,BOOST_PP_COMMA,seq) int) #define FINALLY_END } BOOST_PP_CAT(_finally_guard_,__LINE__) = { _finally_last_params }; #include #include void* _finally_last_params = 0; int main() { int i = 2, j = 1; FINALLY_BEGIN((i)(j)) throw() { std::cerr << i+j << '\n'; } FINALLY_END FINALLY_BEGIN((i)(j)) try { std::cerr << i-j << '\n'; } catch(...) {} FINALLY_END }