// Copyright Alexander Nasonov 2006-2007 // // 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) #ifndef FILE_boost_scope_exit_hpp_INCLUDED #define FILE_boost_scope_exit_hpp_INCLUDED #include #include #include #include #include #include #include #include #include namespace boost { namespace detail { namespace scope_exit { // Don't strip top-level cv-qualifiers from variable types // by using typeof(wrap(variable))::type. template struct wrapper { typedef T type; }; template wrapper wrap(T&); // Ctor starts with an initialization of this class so that an // initialization of other members always starts with a comma. // This makes possible to invoke BOOST_PP_SEQ_FOR_EACH. struct empty_base {}; } } } #if defined(__GNUC__) && !defined(BOOST_INTEL) # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__) #else # define BOOST_SCOPE_EXIT_AUX_GCC 0 #endif #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(304)) #define BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND #endif // Generate var _boost_scope_exit_ what id #define BOOST_SCOPE_EXIT_AUX_NAME2(id_var, what) \ BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(1, id_var), \ BOOST_PP_CAT(boost_scope_exit_, \ BOOST_PP_CAT(what, BOOST_PP_ARRAY_ELEM(0, id_var)))) // Generate var _boost_scope_exit_ what id #define BOOST_SCOPE_EXIT_AUX_NAME3(id_whatever, var, what) \ BOOST_PP_CAT(var, BOOST_PP_CAT(_boost_scope_exit_, \ BOOST_PP_CAT(what, BOOST_PP_ARRAY_ELEM(0, id_whatever)))) // Generate unique name for typeof(var) #define BOOST_SCOPE_EXIT_AUX_TYPE1(id_var) \ BOOST_SCOPE_EXIT_AUX_NAME2(id_var, typeof) // Generate unique name for typeof(var) #define BOOST_SCOPE_EXIT_AUX_TYPE2(id_whatever, var) \ BOOST_SCOPE_EXIT_AUX_NAME3(id_whatever, var, typeof) #define BOOST_SCOPE_EXIT_AUX_VAR(r, _, var) var , #define BOOST_SCOPE_EXIT_AUX_DEREF(r, ptr, var) ptr->var , #define BOOST_SCOPE_EXIT_AUX_INIT(r, ptr, var) , var(var) #if defined(BOOST_TYPEOF_EMULATION) // Generate typedef for typeof(var). // The struct is derived from typeof(wrap(var)) to get rid of typename // in emulation mode. #define BOOST_SCOPE_EXIT_AUX_TYPEDEF(r, id_typename, var) \ struct BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, nested_typeof) \ : BOOST_TYPEOF(::boost::detail::scope_exit::wrap(var)) {}; \ typedef BOOST_PP_ARRAY_ELEM(1, id_typename) \ BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, nested_typeof) ::type \ BOOST_SCOPE_EXIT_AUX_TYPE2(id_typename, var); #elif defined(BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND) // Generate typedef for typeof(var) #define BOOST_SCOPE_EXIT_AUX_TYPEDEF(r, id_typename, var) \ struct BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, nested_typeof) \ { typedef BOOST_TYPEOF(::boost::detail::scope_exit::wrap(var)) \ boost_scope_exit_wrapped; \ typedef BOOST_PP_ARRAY_ELEM(1, id_typename) \ boost_scope_exit_wrapped::type boost_scope_exit_type; }; \ typedef BOOST_PP_ARRAY_ELEM(1, id_typename) \ BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, nested_typeof) \ ::boost_scope_exit_type \ BOOST_SCOPE_EXIT_AUX_TYPE2(id_typename, var); #else // Generate typedef for typeof(var) #define BOOST_SCOPE_EXIT_AUX_TYPEDEF(r, id_typename, var) \ typedef BOOST_TYPEOF(::boost::detail::scope_exit::wrap(var)) \ BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, wrapped); \ typedef BOOST_SCOPE_EXIT_AUX_NAME3(id_typename, var, wrapped) \ ::type BOOST_SCOPE_EXIT_AUX_TYPE2(id_typename, var); #endif #define BOOST_SCOPE_EXIT_AUX_SEMICOLON() ; #define BOOST_SCOPE_EXIT_AUX_REF(r, id_delim, var) \ BOOST_SCOPE_EXIT_AUX_TYPE2(id_delim, var) & var \ BOOST_PP_ARRAY_ELEM(1, id_delim)() // Implementation #define BOOST_SCOPE_EXIT_AUX_IMPL(id, seq, Typename) \ BOOST_PP_SEQ_FOR_EACH( \ BOOST_SCOPE_EXIT_AUX_TYPEDEF, (2, (id, Typename)), seq) \ struct BOOST_PP_CAT(boost_scope_exit_params_struct_, id) \ : boost::detail::scope_exit::empty_base \ { BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_REF, \ (2, (id, BOOST_SCOPE_EXIT_AUX_SEMICOLON)), seq) \ BOOST_PP_CAT(boost_scope_exit_params_struct_, id)( \ BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_REF, \ (2, (id, BOOST_PP_COMMA)), seq) int) \ : boost::detail::scope_exit::empty_base() \ BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_INIT, _, seq) \ {} }; \ BOOST_PP_CAT(boost_scope_exit_params_struct_, id) \ BOOST_PP_CAT(boost_scope_exit_params_, id) \ (BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_VAR, _, seq) 0); \ struct BOOST_PP_CAT(boost_scope_exit_struct_, id) \ { BOOST_PP_CAT(boost_scope_exit_params_struct_, id) * \ boost_scope_exit_params; \ BOOST_PP_CAT(~boost_scope_exit_struct_, id)() \ { boost_scope_exit_fun(boost_scope_exit_params); } \ void (*boost_scope_exit_fun)( \ BOOST_PP_CAT(boost_scope_exit_params_struct_, id) *); \ } BOOST_PP_CAT(boost_scope_exit_, id) = \ { &BOOST_PP_CAT(boost_scope_exit_params_, id) }; \ { BOOST_PP_CAT(boost_scope_exit_struct_, id) * \ boost_scope_exit_ptr = &BOOST_PP_CAT(boost_scope_exit_, id); \ struct boost_scope_exit_body_struct { \ static void boost_scope_exit_entry( \ BOOST_PP_CAT(boost_scope_exit_params_struct_, id) * \ boost_scope_exit_params) \ { boost_scope_exit_body( \ BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_DEREF, \ boost_scope_exit_params, seq) 0); } \ static void boost_scope_exit_body( \ BOOST_PP_SEQ_FOR_EACH(BOOST_SCOPE_EXIT_AUX_REF, \ (2, (id, BOOST_PP_COMMA)), seq) int) #define BOOST_SCOPE_EXIT_END }; boost_scope_exit_ptr->boost_scope_exit_fun = \ &boost_scope_exit_body_struct::boost_scope_exit_entry; } #define BOOST_SCOPE_EXIT(seq) \ BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, BOOST_PP_EMPTY()) #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND #define BOOST_SCOPE_EXIT_TPL(seq) \ BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, typename) #else #define BOOST_SCOPE_EXIT_TPL(seq) BOOST_SCOPE_EXIT(seq) #endif #define BOOST_SCOPE_EXIT_TRY(seq) BOOST_SCOPE_EXIT(seq) try #define BOOST_SCOPE_EXIT_TRY_TPL(seq) BOOST_SCOPE_EXIT_TPL(seq) try #define BOOST_SCOPE_EXIT_CATCH_ALL catch(...) {} BOOST_SCOPE_EXIT_END #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TEMPLATE( ::boost::detail::scope_exit::wrapper, 1) #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED