1 // Copyright Alexander Nasonov 2006-2009
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef FILE_boost_scope_exit_hpp_INCLUDED
8 #define FILE_boost_scope_exit_hpp_INCLUDED
10 #include <boost/config.hpp>
12 #include <boost/detail/workaround.hpp>
13 #include <boost/preprocessor/cat.hpp>
14 #include <boost/preprocessor/facilities/empty.hpp>
15 #include <boost/preprocessor/punctuation/comma_if.hpp>
16 #include <boost/preprocessor/seq/cat.hpp>
17 #include <boost/preprocessor/seq/for_each_i.hpp>
18 #include <boost/preprocessor/tuple/elem.hpp>
19 #include <boost/typeof/typeof.hpp>
21 #if defined(__GNUC__) && !defined(BOOST_INTEL)
22 # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
24 # define BOOST_SCOPE_EXIT_AUX_GCC 0
27 #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
28 #define BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
31 // Steven Watanabe's trick with a modification suggested by Kim Barrett
32 namespace boost { namespace scope_exit { namespace aux {
34 // Type of a local boost_scope_exit_args variable.
35 // First use in a local scope will declare the boost_scope_exit_args
36 // variable, subsequent uses will be resolved as two comparisons
37 // (cmp1 with 0 and cmp2 with boost_scope_exit_args).
38 template<int Dummy = 0>
42 static int const cmp2 = 0;
43 friend void operator>(int, declared const&) {}
46 struct undeclared { declared<> dummy[2]; };
48 template<int> struct resolve;
51 struct resolve<sizeof(declared<>)>
53 static const int cmp1 = 0;
57 struct resolve<sizeof(undeclared)>
62 static int const cmp2 = 0;
67 extern boost::scope_exit::aux::undeclared boost_scope_exit_args; // undefined
70 namespace boost { namespace scope_exit { namespace aux {
72 typedef void (*ref_tag)(int&);
73 typedef void (*val_tag)(int );
75 template<class T, class Tag> struct member;
78 struct member<T,ref_tag>
81 #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
82 member(T& ref) : value(ref) {}
87 struct member<T,val_tag>
90 #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
91 member(T& val) : value(val) {}
95 template<class T> inline T& deref(T* p, ref_tag) { return *p; }
96 template<class T> inline T& deref(T& r, val_tag) { return r; }
104 template<class T> wrapper<T> wrap(T&);
108 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
109 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::aux::wrapper, 1)
111 #define BOOST_SCOPE_EXIT_AUX_GUARD(id) BOOST_PP_CAT(boost_se_guard_, id)
112 #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) BOOST_PP_CAT(boost_se_guard_t_, id)
113 #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_PP_CAT(boost_se_params_, id)
114 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) BOOST_PP_CAT(boost_se_params_t_, id)
116 #define BOOST_SCOPE_EXIT_AUX_TAG(id, i) \
117 BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
119 #define BOOST_SCOPE_EXIT_AUX_PARAM(id, i, var) \
120 BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
122 #define BOOST_SCOPE_EXIT_AUX_PARAM_T(id, i, var) \
123 BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
125 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_T(id, i, var) \
126 BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
128 #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
129 BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
131 #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
132 boost::scope_exit::aux::deref(var, (BOOST_SCOPE_EXIT_AUX_TAG(id,i))0)
134 #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
135 boost::scope_exit::aux::member< \
136 BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var), \
137 BOOST_SCOPE_EXIT_AUX_TAG(id,i) \
138 > BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var);
140 // idty is (id,typename) or (id,BOOST_PP_EMPTY())
141 #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, idty, i, var) \
142 BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) \
143 BOOST_SCOPE_EXIT_AUX_PARAMS_T(BOOST_PP_TUPLE_ELEM(2,0,idty)):: \
144 BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) var
146 #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
147 boost_se_params_->BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var).value
149 #define BOOST_SCOPE_EXIT_AUX_TAG_DECL(r, id, i, var) \
150 typedef void (*BOOST_SCOPE_EXIT_AUX_TAG(id,i))(int var);
153 #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
155 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq)
157 #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
158 BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var) }
160 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
161 = { BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) };
165 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
166 BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var) & BOOST_PP_CAT(a,i)
168 #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) BOOST_PP_COMMA_IF(i) \
169 BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var) ( BOOST_PP_CAT(a,i) )
171 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
172 BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)( \
173 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, seq ) ) \
174 : BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, seq) {}
176 #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
177 BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
179 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
180 ( BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) );
184 #if defined(BOOST_TYPEOF_EMULATION)
186 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
187 struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i) \
188 : BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
189 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
190 {}; typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
191 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
192 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
194 #elif defined(BOOST_INTEL)
196 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
197 typedef BOOST_TYPEOF_KEYWORD( \
198 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var)) \
199 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
203 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
204 typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
205 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
206 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i); \
207 typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
208 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
209 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
213 #define BOOST_SCOPE_EXIT_AUX_PARAM_DECL(r, idty, i, var) \
214 typedef BOOST_SCOPE_EXIT_AUX_CAPTURE_T( \
215 BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) \
216 BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
219 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, seq, ty) \
220 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_TAG_DECL, id, seq) \
221 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL, (id,ty), seq) \
222 struct BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) { \
223 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_DECL, (id,ty), seq) \
224 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, seq) \
225 BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
226 } BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id,seq) \
227 boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< \
228 sizeof(boost_scope_exit_args)>::cmp1<0>::cmp2 > boost_scope_exit_args; \
229 boost_scope_exit_args.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
230 struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
231 BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)* boost_se_params_; \
232 BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
233 : boost_se_params_( \
234 (BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)*)boost_se_params) \
236 ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { boost_se_body( \
237 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, seq) ); } \
238 static void boost_se_body(BOOST_PP_SEQ_FOR_EACH_I( \
239 BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id,ty), seq) )
241 #if defined(BOOST_MSVC)
243 #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__COUNTER__) ( \
244 boost_scope_exit_args.value);
246 #define BOOST_SCOPE_EXIT(seq) \
247 BOOST_SCOPE_EXIT_AUX_IMPL(__COUNTER__, seq, BOOST_PP_EMPTY())
251 #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__LINE__) ( \
252 boost_scope_exit_args.value);
254 #define BOOST_SCOPE_EXIT(seq) \
255 BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, BOOST_PP_EMPTY())
259 #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
260 #define BOOST_SCOPE_EXIT_TPL(seq) \
261 BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, typename)
263 #define BOOST_SCOPE_EXIT_TPL(seq) BOOST_SCOPE_EXIT(seq)
266 #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED