2 // Copyright (C) 2006-2009, 2012 Alexander Nasonov
3 // Copyright (C) 2012 Lorenzo Caminiti
4 // Distributed under the Boost Software License, Version 1.0
5 // (see accompanying file LICENSE_1_0.txt or a copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 // Home at http://www.boost.org/libs/scope_exit
9 #ifndef FILE_boost_scope_exit_hpp_INCLUDED
10 #define FILE_boost_scope_exit_hpp_INCLUDED
14 #include <boost/detail/workaround.hpp>
15 #include <boost/mpl/assert.hpp>
16 #include <boost/mpl/int.hpp>
17 #include <boost/utility/enable_if.hpp>
18 #include <boost/function.hpp>
19 #include <boost/typeof/typeof.hpp>
20 #include <boost/config.hpp>
21 #include <boost/preprocessor/cat.hpp>
22 #include <boost/preprocessor/control/iif.hpp>
23 #include <boost/preprocessor/control/expr_iif.hpp>
24 #include <boost/preprocessor/comparison/equal.hpp>
25 #include <boost/preprocessor/logical/bitor.hpp>
26 #include <boost/preprocessor/logical/bitand.hpp>
27 #include <boost/preprocessor/facilities/empty.hpp>
28 #include <boost/preprocessor/facilities/is_empty.hpp>
29 #include <boost/preprocessor/facilities/identity.hpp>
30 #include <boost/preprocessor/punctuation/comma_if.hpp>
31 #include <boost/preprocessor/punctuation/paren_if.hpp>
32 #include <boost/preprocessor/seq/cat.hpp>
33 #include <boost/preprocessor/seq/size.hpp>
34 #include <boost/preprocessor/seq/to_tuple.hpp>
35 #include <boost/preprocessor/tuple/elem.hpp>
36 #include <boost/preprocessor/tuple/eat.hpp>
37 #include <boost/preprocessor/tuple/to_list.hpp>
38 #include <boost/preprocessor/list/append.hpp>
39 #include <boost/preprocessor/list/fold_left.hpp>
40 #include <boost/preprocessor/list/enum.hpp>
41 #include <boost/preprocessor/list/adt.hpp>
42 #include <boost/preprocessor/list/for_each_i.hpp>
43 #include <boost/preprocessor/detail/is_unary.hpp>
45 // PRIVATE/PROTECTED //
47 // NOTE: AUX prefix and aux namespace mark "private" symbols that shall be used
48 // only within this library; DETAIL prefix and detail namespace mark "protected"
49 // symbols that can be used by other Boost libraries but not outside Boost.
51 // WARNING: BOOST_SCOPE_EXIT_AUX_GCC also used by some regression test.
52 #if defined(__GNUC__) && !defined(BOOST_INTEL)
53 # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
55 # define BOOST_SCOPE_EXIT_AUX_GCC 0
58 #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
59 # define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 1
61 # define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 0
65 # define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 1
67 # define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 0
70 // MSVC has problems expanding __LINE__ so use (the non standard) __COUNTER__.
72 # define BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER __COUNTER__
74 # define BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER __LINE__
77 // Preprocessor "keyword" detection.
79 // These are not a local macros, do not #undefine them (these are used by the
80 // ..._BACK macros below).
81 #define this_BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_THISUNDERSCORE_IS (1) /* unary */
82 #define void_BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_VOID_IS (1) /* unary */
84 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, checking_postfix) \
85 BOOST_PP_IS_UNARY(BOOST_PP_CAT(token, checking_postfix))
87 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_THISUNDERSCORE_BACK(token) \
88 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, \
89 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_THISUNDERSCORE_IS)
91 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK(token) \
92 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, \
93 _BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_VOID_IS)
95 // Preprocessor "void-list".
97 // NOTE: Empty list must always be represented as void (which is also a way to
98 // specify no function parameter) and it can never be empty because (1)
99 // IS_EMPTY(&var) fails (because of the leading non alphanumeric symbol) and
100 // (2) some compilers (MSVC) fail to correctly pass empty macro parameters
101 // even if they support variadic macros. Therefore, always using void to
102 // represent is more portable.
104 // Argument: (token1)...
105 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_SEQ_(unused, seq) \
106 BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), BOOST_PP_SEQ_TO_TUPLE(seq))
108 // Token: void | token1
109 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_VOID_( \
110 is_void_macro, token) \
111 BOOST_PP_IIF(is_void_macro(token), \
114 (token, BOOST_PP_NIL) \
117 // Token: (a)(b)... | empty | void | token
118 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_( \
119 is_void_macro, token) \
120 BOOST_PP_IIF(BOOST_PP_IS_UNARY(token), /* unary paren (a)... */ \
121 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_SEQ_ \
123 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_VOID_ \
124 )(is_void_macro, token)
126 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_(tokens) \
127 0 /* void check always returns false */
129 #ifdef BOOST_NO_CXX11_VARIADIC_MACROS
131 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_(is_void_macro, seq) \
132 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_(is_void_macro, seq)
134 // Expand `void | (a)(b)...` to pp-list `NIL | (a, (b, NIL))`.
135 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(sign) \
136 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
137 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK, sign)
139 // Expand `(a)(b)...` to pp-list `(a, (b, NIL))`.
140 #define BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(seq) \
141 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
142 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_, seq)
146 // FUTURE: Replace this with BOOST_PP_VARIADIC_SIZE when and if
147 // BOOST_PP_VARIAIDCS detection will match !BOOST_NO_CXX11_VARIADIC_MACROS (for
148 // now Boost.Preprocessor and Boost.Config disagree on detecting compiler
149 // variadic support while this VARIADIC_SIZE works on compilers not detected by
152 # define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_(...) \
153 BOOST_PP_CAT(BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_I_(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,),)
155 # define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_(...) \
156 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_I_(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)
158 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_I_(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, size, ...) size
160 // Argument: token1, ...
161 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_VARIADIC_(unused, ...) \
162 BOOST_PP_TUPLE_TO_LIST( \
163 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_( \
164 __VA_ARGS__), (__VA_ARGS__))
166 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_(is_void_macro, ...) \
167 BOOST_PP_IIF(BOOST_PP_EQUAL( \
168 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_( \
170 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_ \
172 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_VARIADIC_ \
173 )(is_void_macro, __VA_ARGS__)
175 // Expand `void | (a)(b)... | a, b, ...` to pp-list `NIL | (a, (b, NIL))`.
176 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(...) \
177 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
178 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK, __VA_ARGS__)
180 // Expand `(a)(b)... | a, b, ...` to pp-list `(a, (b, NIL))`.
181 #define BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(...) \
182 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
183 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_, __VA_ARGS__)
187 // Steven Watanabe's trick with a modification suggested by Kim Barrett
188 namespace boost { namespace scope_exit { namespace detail {
190 // Type of a local BOOST_SCOPE_EXIT_AUX_ARGS variable.
191 // First use in a local scope will declare the BOOST_SCOPE_EXIT_AUX_ARGS
192 // variable, subsequent uses will be resolved as two comparisons
193 // (cmp1 with 0 and cmp2 with BOOST_SCOPE_EXIT_AUX_ARGS).
194 template<int Dummy = 0>
198 static int const cmp2 = 0;
199 friend void operator>(int, declared const&) {}
202 struct undeclared { declared<> dummy[2]; };
204 template<int> struct resolve;
207 struct resolve<sizeof(declared<>)>
209 static const int cmp1 = 0;
213 struct resolve<sizeof(undeclared)>
218 static int const cmp2 = 0;
222 typedef void (*ref_tag)(int&);
223 typedef void (*val_tag)(int );
225 template<class T, class Tag> struct member;
228 struct member<T,ref_tag>
231 #if !BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
232 member(T& ref) : value(ref) {}
237 struct member<T,val_tag>
240 #if !BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
241 member(T& val) : value(val) {}
245 template<class T> inline T& deref(T* p, ref_tag) { return *p; }
246 template<class T> inline T& deref(T& r, val_tag) { return r; }
254 template<class T> wrapper<T> wrap(T&);
258 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
259 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::detail::wrapper, 1)
261 #define BOOST_SCOPE_EXIT_AUX_ARGS boost_scope_exit_aux_args
262 extern boost::scope_exit::detail::undeclared BOOST_SCOPE_EXIT_AUX_ARGS;
264 #define BOOST_SCOPE_EXIT_AUX_GUARD(id) \
265 BOOST_PP_CAT(boost_se_guard_, id)
267 #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) \
268 BOOST_PP_CAT(boost_se_guard_t_, id)
270 #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) \
271 BOOST_PP_CAT(boost_se_params_, id)
273 #define BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
274 BOOST_PP_CAT(boost_se_this_t_, id)
276 #define BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id) \
277 BOOST_PP_CAT(boost_se_this_capture_t_, id)
279 #define BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) \
280 BOOST_PP_CAT(boost_se_params_t_, id)
282 #define BOOST_SCOPE_EXIT_DETAIL_TAG(id, i) \
283 BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
285 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) \
286 BOOST_PP_SEQ_CAT( (boost_se_param_this_)(id) )
288 #define BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var) \
289 BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
291 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var) \
292 BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
294 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(id, i, var) \
295 BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
297 #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
298 BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
300 #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
301 ::boost::scope_exit::detail::deref(var, \
302 static_cast<BOOST_SCOPE_EXIT_DETAIL_TAG(id, i)>(0))
304 #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
305 ::boost::scope_exit::detail::member< \
306 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var), \
307 BOOST_SCOPE_EXIT_DETAIL_TAG(id, i) \
308 > BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var);
310 #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, id_ty, i, var) \
311 BOOST_PP_COMMA_IF(i) \
312 BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
313 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty)):: \
314 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
318 #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) \
319 BOOST_PP_COMMA_IF(i) \
320 boost_se_params_->BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var).value
322 #define BOOST_SCOPE_EXIT_DETAIL_TAG_DECL(r, id, i, var) \
323 typedef void (*BOOST_SCOPE_EXIT_DETAIL_TAG(id, i))(int var);
325 // Adam Butcher's workaround to deduce `this` type on MSVC revision < 10.
326 // Boost.Typeof for VC71's typeid-based workaround does not work to determine
327 // `this` type due to error C2355 being incorrectly reported. The typical
328 // avoidance strategy implemented below is to make an indirect compile-time
329 // constant by assigning an enum and use that as type-index-- this only works
330 // with the sizeof() approach and not with the typeid() approach. Lorenzo
331 // Caminiti extended this approach to work in type-of emulation mode. This code
332 // is very similar (and somewhat of a duplication) of the code in
333 // boost/typeof/msvc/typeof_impl.hpp). However, this code cannot be integrated
334 // into Boost.Typeof because its final API has to be a `typedef ...` and it
335 // cannot be a `typeof(...)`.
336 #if BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01
338 #include <boost/config.hpp>
339 #include <boost/detail/workaround.hpp>
340 #include <boost/mpl/int.hpp>
341 #include <boost/type_traits/is_function.hpp>
342 #include <boost/utility/enable_if.hpp>
344 #if defined(BOOST_MSVC)
348 namespace boost { namespace scope_exit { namespace aux {
349 namespace msvc_typeof_this {
351 // compile-time constant code
352 #if defined(BOOST_MSVC) && defined(_MSC_EXTENSIONS)
354 template<int N> struct the_counter;
356 template<typename T,int N = 5 /* for similarity */>
357 struct encode_counter {
358 __if_exists(the_counter<N + 256>) {
359 BOOST_STATIC_CONSTANT(unsigned,
360 count=(encode_counter<T,N + 257>::count));
362 __if_not_exists(the_counter<N + 256>) {
363 __if_exists(the_counter<N + 64>) {
364 BOOST_STATIC_CONSTANT(unsigned,
365 count=(encode_counter<T,N + 65>::count));
367 __if_not_exists(the_counter<N + 64>) {
368 __if_exists(the_counter<N + 16>) {
369 BOOST_STATIC_CONSTANT(unsigned,
370 count=(encode_counter<T,N + 17>::count));
372 __if_not_exists(the_counter<N + 16>) {
373 __if_exists(the_counter<N + 4>) {
374 BOOST_STATIC_CONSTANT(unsigned,
375 count=(encode_counter<T,N + 5>::count));
377 __if_not_exists(the_counter<N + 4>) {
378 __if_exists(the_counter<N>) {
379 BOOST_STATIC_CONSTANT(unsigned,
380 count=(encode_counter<T,N + 1>::count));
382 __if_not_exists(the_counter<N>) {
383 BOOST_STATIC_CONSTANT(unsigned,count=N);
384 typedef the_counter<N> type;
392 #else // compile-time constant code
394 template<int N> struct encode_counter : encode_counter<N - 1> {};
396 template<> struct encode_counter<0> {};
398 #endif // compile-time constant code
400 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) // type-of code
402 struct msvc_extract_type_default_param {};
404 template<typename ID, typename T = msvc_extract_type_default_param>
405 struct msvc_extract_type;
407 template<typename ID>
408 struct msvc_extract_type<ID, msvc_extract_type_default_param> {
412 typedef id2type_impl<true> id2type;
415 template<typename ID, typename T>
416 struct msvc_extract_type
417 : msvc_extract_type<ID, msvc_extract_type_default_param> {
419 struct id2type_impl<true> { // VC8.0 specific bug-feature.
426 typedef id2type_impl<true> id2type;
429 template<typename T, typename ID>
430 struct msvc_register_type : msvc_extract_type<ID, T> {};
432 #else // type-of code
434 template<typename ID>
435 struct msvc_extract_type {
439 template<typename T, typename ID>
440 struct msvc_register_type : msvc_extract_type<ID> {
441 typedef msvc_extract_type<ID> base_type;
442 struct base_type::id2type { // This uses nice VC6.5 and VC7.1 bug-features.
447 #endif // typeof code
450 struct msvc_typeid_wrapper {
451 typedef typename msvc_extract_type<boost::mpl::int_<Id>
453 typedef typename id2type::type type;
457 struct msvc_typeid_wrapper<4> {
458 typedef msvc_typeid_wrapper<4> type;
463 BOOST_STATIC_CONSTANT(unsigned, value = encode_counter<T>::count);
464 typedef typename msvc_register_type<T,
465 boost::mpl::int_<value> >::id2type type;
466 BOOST_STATIC_CONSTANT(unsigned, next = value + 1);
471 typedef char(*type)[encode_type<T>::value];
475 typename boost::disable_if<
476 typename boost::is_function<T>::type
477 , typename sizer<T>::type
478 >::type encode_start(T const&);
481 typename boost::enable_if<
482 typename boost::is_function<T>::type
483 , typename sizer<T>::type
484 >::type encode_start(T&);
486 template<typename Organizer, typename T>
487 msvc_register_type<T, Organizer> typeof_register_type(const T&,
492 #define BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
493 BOOST_PP_CAT(boost_se_thistype_index_, id)
495 #define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, new_type) \
496 /* unfortunately, we need to go via this enum which causes this to be */ \
497 /* a typedef construct and not a typeof (so this code cannot be */ \
498 /* integrated into Boost.Typeof) */ \
500 BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) = sizeof( \
501 *::boost::scope_exit::aux::msvc_typeof_this::encode_start(this)) \
504 ty ::boost::scope_exit::aux::msvc_typeof_this::msvc_typeid_wrapper< \
505 BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
510 #else // TYPEOF_THIS_MSVC_WORKAROUND
512 #define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, new_type) \
513 typedef /* trailing `EMPTY()` handles empty `ty` */ \
514 BOOST_PP_IIF(BOOST_PP_IS_EMPTY(ty BOOST_PP_EMPTY()), \
522 #endif // TYPEOF_THIS_MSVC_WORKAROUND
524 #if BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
526 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, captures, has_this) \
527 /* expand to nothing */
529 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT(r, id, i, var) \
530 BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) }
532 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, captures, has_this) \
533 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(has_this, \
534 BOOST_PP_LIST_IS_CONS(captures)), \
537 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT, id, captures) \
538 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS(captures), \
540 BOOST_PP_EXPR_IIF(has_this, this) /* no extra {...} needed here */ \
541 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(has_this, \
542 BOOST_PP_LIST_IS_CONS(captures)), \
543 } /* trailing `;` will be added by the caller */ \
546 #else // TPL_GCC_WORKAROUND
548 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) \
549 BOOST_PP_COMMA_IF(i) \
550 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var) & BOOST_PP_CAT(a, i)
552 #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) \
553 BOOST_PP_COMMA_IF(i) \
554 BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var) ( BOOST_PP_CAT(a, i) )
556 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id) \
557 BOOST_PP_CAT(boost_se_this_arg_, id)
559 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS(id, ty, comma01) \
560 BOOST_PP_COMMA_IF(comma01) \
561 ty BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)::BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
562 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id) /* ptr so no & */
564 #define BOOST_SCOPE_EXIT_AUX_MEMBER_THIS_INIT(id, comma01) \
565 BOOST_PP_COMMA_IF(comma01) \
566 BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id)( \
567 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id))
569 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, captures, has_this) \
570 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)( \
571 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, captures) \
572 BOOST_PP_IIF(has_this, \
573 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS \
575 BOOST_PP_TUPLE_EAT(3) \
576 )(id, ty, BOOST_PP_LIST_IS_CONS(captures)) \
578 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(BOOST_PP_LIST_IS_CONS(captures), \
582 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, \
584 BOOST_PP_IIF(has_this, \
585 BOOST_SCOPE_EXIT_AUX_MEMBER_THIS_INIT \
587 BOOST_PP_TUPLE_EAT(2) \
588 )(id, BOOST_PP_LIST_IS_CONS(captures)) \
591 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT(r, id, i, var) \
592 BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
594 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, captures, has_this) \
595 BOOST_PP_LPAREN_IF(BOOST_PP_BITOR(has_this, \
596 BOOST_PP_LIST_IS_CONS(captures))) \
597 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT, id, captures) \
598 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS(captures), \
600 BOOST_PP_EXPR_IIF(has_this, this) \
601 BOOST_PP_RPAREN_IF(BOOST_PP_BITOR(has_this, \
602 BOOST_PP_LIST_IS_CONS(captures)))
604 #endif // TPL_GCC_WORKAROUND
606 #if defined(BOOST_TYPEOF_EMULATION)
608 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
609 struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i) \
610 /* no need to use TYPEOF_TPL here because it's within inheritance */ \
611 : BOOST_TYPEOF(::boost::scope_exit::detail::wrap( \
612 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
615 typedef BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
616 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i)::type\
617 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
621 #elif defined(BOOST_INTEL)
623 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
625 /* no TYPEOF_TPL here because uses TYPEOF_KEYWORD directly */ \
626 BOOST_TYPEOF_KEYWORD(BOOST_SCOPE_EXIT_AUX_DEREF( \
627 BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i, var)) \
628 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
634 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
636 /* no need to use TYPEOF_TPL here because it's a typedef */ \
637 BOOST_TYPEOF(::boost::scope_exit::detail::wrap( \
638 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
640 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i) \
642 typedef BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
643 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i)::type\
644 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
650 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_DECL(r, id_ty, i, var) \
652 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
654 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
660 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP_CAPTURE(d, captures, this01, capture) \
661 (BOOST_PP_LIST_APPEND(captures, (capture, BOOST_PP_NIL)), this01)
663 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP_THIS(d, captures, this01, this_) \
664 (captures, 1 /* has this (note, no error if multiple this_) */)
666 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP(d, captures_this, capture) \
667 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_THISUNDERSCORE_BACK(\
669 BOOST_SCOPE_EXIT_AUX_TRAITS_OP_THIS \
671 BOOST_SCOPE_EXIT_AUX_TRAITS_OP_CAPTURE \
672 )(d, BOOST_PP_TUPLE_ELEM(2, 0, captures_this), \
673 BOOST_PP_TUPLE_ELEM(2, 1, captures_this), capture)
676 #define BOOST_SCOPE_EXIT_AUX_TRAITS_ALL_OP(ref_val, traits) \
678 BOOST_PP_LIST_APPEND((ref_val, BOOST_PP_NIL), \
679 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
681 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits) \
684 #define BOOST_SCOPE_EXIT_AUX_TRAITS(captures) \
685 BOOST_PP_LIST_FOLD_LEFT(BOOST_SCOPE_EXIT_AUX_TRAITS_OP, \
686 (BOOST_PP_NIL, 0), captures)
688 #define BOOST_SCOPE_EXIT_AUX_TRAITS_ALL(captures) \
689 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL_OP(BOOST_PP_LIST_FIRST(captures), \
690 BOOST_SCOPE_EXIT_AUX_TRAITS(BOOST_PP_LIST_REST(captures)))
692 #define BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits) \
693 BOOST_PP_TUPLE_ELEM(2, 0, traits)
695 #define BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits) \
696 BOOST_PP_TUPLE_ELEM(2, 1, traits)
698 #ifndef BOOST_NO_CXX11_LAMBDAS
700 namespace boost { namespace scope_exit { namespace aux {
702 template<typename This = void>
703 struct guard { // With object `this_` (for backward compatibility).
704 explicit guard(This _this) : this_(_this) {}
705 ~guard() { if(f_) f_(this_); }
706 template<typename Lambda>
707 void operator=(Lambda f) { f_ = f; }
710 boost::function<void (This)> f_;
714 struct guard<void> { // Without object `this_` (could capture `this` directly).
715 ~guard() { if(f_) f_(); }
716 template<typename Lambda>
717 void operator=(Lambda f) { f_ = f; }
719 boost::function<void (void)> f_;
724 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id) \
725 BOOST_PP_CAT(boost_se_lambda_params_, id)
727 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id) \
728 BOOST_PP_CAT(boost_se_lambda_this_t_, id)
730 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id) \
731 BOOST_PP_CAT(boost_se_lambda_this_capture_t_, id)
733 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE(id, ty) \
734 ty BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id):: \
735 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id)
737 // Precondition: HAS_THIS(traits).
738 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPEDEFS(id, ty, traits) \
739 BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, \
740 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id)) \
741 /* capture type for workaround GCC internal error (even on later C++11) */ \
742 struct BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id) { \
743 typedef BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id) \
744 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id); \
747 #define BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, ty, traits) \
748 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
749 /* no need for TYPEDEF THIS MSVC workaround on C++11 */ \
750 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPEDEFS \
752 BOOST_PP_TUPLE_EAT(3) \
754 ::boost::scope_exit::aux::guard< \
755 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
756 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE \
758 BOOST_PP_TUPLE_EAT(2) \
760 > BOOST_SCOPE_EXIT_AUX_GUARD(id) \
761 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
765 BOOST_SCOPE_EXIT_AUX_GUARD(id) = [ \
766 BOOST_PP_LIST_ENUM(BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
768 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
769 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE \
771 BOOST_PP_TUPLE_EAT(2) \
773 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), this_) \
774 ) mutable /* can change value captures (as with SCOPE_EXIT) */ -> void
778 #if defined(BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS) && \
779 !defined(BOOST_NO_CXX11_LAMBDAS) // Use lambda for SCOPE_EXIT (not just _ALL).
781 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, ty, traits) \
782 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, ty, traits)
784 #else // Not using lambdas.
786 // ty: EMPTY() | typename
787 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, ty, traits) \
788 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_TAG_DECL, id, \
789 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
790 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL, (id, ty), \
791 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
792 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
793 BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS \
795 BOOST_PP_TUPLE_EAT(3) \
796 )(id, ty, BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id)) \
797 struct BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) { \
798 /* interim capture types to workaround internal errors on old GCC */ \
799 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_DECL, (id, ty), \
800 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
801 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
802 typedef BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id) \
803 BOOST_SCOPE_EXIT_AUX_THIS_T(id) ; \
805 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, \
806 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
807 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
808 BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
809 BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) ; \
811 BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, \
812 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits), \
813 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits)) \
814 } BOOST_SCOPE_EXIT_AUX_PARAMS(id) \
815 BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, \
816 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits), \
817 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits)) \
819 ::boost::scope_exit::detail::declared< \
820 ::boost::scope_exit::detail::resolve< \
821 sizeof(BOOST_SCOPE_EXIT_AUX_ARGS) \
823 > BOOST_SCOPE_EXIT_AUX_ARGS; \
824 BOOST_SCOPE_EXIT_AUX_ARGS.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
825 struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
826 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)* boost_se_params_; \
827 BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
828 : boost_se_params_( \
829 (BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)*)boost_se_params) \
831 ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { \
833 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, \
834 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
835 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS( \
836 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)), \
837 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits))) \
838 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS( \
840 boost_se_params_->BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) \
844 static void boost_se_body( \
845 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id, ty), \
846 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
847 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS( \
848 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)), \
849 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits))) \
850 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
851 ty BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id):: \
852 BOOST_SCOPE_EXIT_AUX_THIS_T(id) this_ \
856 #endif // Using lambdas.
860 #if defined(BOOST_NO_CXX11_VARIADIC_MACROS) // No variadic macros (sequences only).
861 # define BOOST_SCOPE_EXIT_ID(id, void_or_seq) \
862 BOOST_SCOPE_EXIT_AUX_IMPL(id, BOOST_PP_EMPTY(), \
863 BOOST_SCOPE_EXIT_AUX_TRAITS( \
864 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(void_or_seq)))
865 # define BOOST_SCOPE_EXIT_ID_TPL(id, void_or_seq) \
866 BOOST_SCOPE_EXIT_AUX_IMPL(id, typename, \
867 BOOST_SCOPE_EXIT_AUX_TRAITS( \
868 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(void_or_seq)))
869 # define BOOST_SCOPE_EXIT(void_or_seq) \
870 BOOST_SCOPE_EXIT_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
872 # define BOOST_SCOPE_EXIT_TPL(void_or_seq) \
873 BOOST_SCOPE_EXIT_ID_TPL(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
875 # if !defined(BOOST_NO_CXX11_LAMBDAS)
876 # define BOOST_SCOPE_EXIT_ALL_ID(id, seq) \
877 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, \
878 /* C++11 allows to use typename outside templates so */ \
879 /* always typename here and no need for ..._ALL_TPL */ \
880 /* (if a C++11 compiler does not implement this use of */ \
881 /* typename, always use `this` instead of `this_`) */ \
883 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL( \
884 BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(seq)))
885 # define BOOST_SCOPE_EXIT_ALL(seq) \
886 BOOST_SCOPE_EXIT_ALL_ID( \
887 BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, seq)
889 #else // Variadic macros (both sequences and variadic tuples).
890 # define BOOST_SCOPE_EXIT_ID(id, ...) \
891 BOOST_SCOPE_EXIT_AUX_IMPL(id, BOOST_PP_EMPTY(), \
892 BOOST_SCOPE_EXIT_AUX_TRAITS( \
893 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(__VA_ARGS__)))
894 # define BOOST_SCOPE_EXIT_ID_TPL(id, ...) \
895 BOOST_SCOPE_EXIT_AUX_IMPL(id, typename, \
896 BOOST_SCOPE_EXIT_AUX_TRAITS( \
897 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(__VA_ARGS__)))
898 # define BOOST_SCOPE_EXIT(...) \
899 BOOST_SCOPE_EXIT_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
901 # define BOOST_SCOPE_EXIT_TPL(...) \
902 BOOST_SCOPE_EXIT_ID_TPL(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
904 # if !defined(BOOST_NO_CXX11_LAMBDAS)
905 # define BOOST_SCOPE_EXIT_ALL_ID(id, ...) \
906 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, \
907 /* C++11 allows to use typename outside templates so */ \
908 /* always typename here and no need for ..._ALL_TPL */ \
909 /* (if a C++11 compiler does not implement this use of */ \
910 /* typename, always use `this` instead of `this_`) */ \
912 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL( \
913 BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST( \
915 # define BOOST_SCOPE_EXIT_ALL(...) \
916 BOOST_SCOPE_EXIT_ALL_ID( \
917 BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, __VA_ARGS__)
921 #if defined(BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS) && \
922 !defined(BOOST_NO_CXX11_LAMBDAS) // Use lambdas for SCOPE_EXIT (not just ALL).
923 # define BOOST_SCOPE_EXIT_END_ID(id) \
924 ; /* lambdas ended with just `;` */
925 #else // Not using lambdas.
926 # define BOOST_SCOPE_EXIT_END_ID(id) \
927 } BOOST_SCOPE_EXIT_AUX_GUARD(id)(BOOST_SCOPE_EXIT_AUX_ARGS.value);
928 #endif // Using lambdas.
929 #define BOOST_SCOPE_EXIT_END \
930 BOOST_SCOPE_EXIT_END_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER)
937 @brief Scope exits allow to execute arbitrary code when the enclosing scope
942 @brief This macro declares a scope exit.
944 The scope exit declaration schedules the execution of the scope exit body at
945 the exit of the enclosing scope:
948 { // Some local scope.
950 BOOST_SCOPE_EXIT(capture_list) {
952 } BOOST_SCOPE_EXIT_END
957 The enclosing scope must be local.
958 If multiple scope exits are declared within the same enclosing scope, the scope
959 exit bodies are executed in the reversed order of their declarations.
960 Note how the end of the scope exit body must be marked by
961 @RefMacro{BOOST_SCOPE_EXIT_END}.
965 On compilers that support variadic macros (see also Boost.Config
966 <c>BOOST_NO_CXX11_VARIADIC_MACROS</c>)\, the capture list syntax is defined by the
970 void | capture_tuple | capture_sequence
972 capture\, capture\, ...
974 (capture) (capture) ...
978 On compilers that do not support variadic macros\, <c>capture_tuple</c> cannot
982 void | capture_sequence
984 Furthermore\, if @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS} is defined on
985 C++11 compilers that support lambda functions (i.e.\, Boost.Config's <c>BOOST_NO_CXX11_LAMBDAS</c> is not defined) then a semicolon <c>;</c> can be used instead of
986 @RefMacro{BOOST_SCOPE_EXIT_END} and <c>this</c> can be used instead of
990 [&]variable | this_ | this
993 (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or
994 <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing;
995 <c>{expression}</c> means the tokens resulting from the expression.)
999 Note that on compilers that support variadic macros (most of moder compliers
1000 and all C++11 compilers), the capture list can be specified as a
1001 comma-separated list of tokens (this is the preferred syntax).
1002 However, on all compilers the same macro @RefMacro{BOOST_SCOPE_EXIT} also
1003 allows to specify the capture list as a Boost.Preprocessor sequence of tokens
1004 (for supporting compilers without variadic macros and for backward compatibility with older versions of this library).
1006 The name <c>variable</c> of each captured variable must be a valid name in the
1007 enclosing scope and it must appear exactly once in the capture list.
1008 If a capture starts with the ampersand sign <c>&</c>, the corresponding
1009 variable will be available by reference within the scope exit body; otherwise,
1010 a copy of the variable will be made at the point of the scope exit declaration
1011 and that copy will be available inside the scope exit body (in this case, the
1012 variable's type must be <c>CopyConstructible</c>).
1014 From within a member function, the object <c>this</c> can be captured using the
1015 special name <c>this_</c> in both the capture list and the scope exit body
1016 (using <c>this</c> instead of <c>this_</c> in the scope exit body leads to
1017 undefined behaviour).
1019 It is possible to capture no variable by specifying the capture list as
1020 <c>void</c> (regardless of variadic macro support).
1022 Only variables listed in the capture list, static variables, <c>extern</c>
1023 variables, global variables, functions, and enumerations from the enclosing
1024 scope can be used inside the scope exit body.
1026 On various GCC versions the special macro @RefMacro{BOOST_SCOPE_EXIT_TPL} must
1027 be used instead of @RefMacro{BOOST_SCOPE_EXIT} within templates (to maximize
1028 portability, it is recommended to always use @RefMacro{BOOST_SCOPE_EXIT_TPL}
1031 On C++11, it is possible capture all variables in scope without listing their
1032 names one-by-one using the macro @RefMacro{BOOST_SCOPE_EXIT_ALL}.
1034 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ID} must be used
1035 instead of @RefMacro{BOOST_SCOPE_EXIT} when it is necessary to expand multiple
1036 scope exit declarations on the same line.
1038 @Warning The implementation executes the scope exit body within a destructor
1039 thus the scope exit body must never throw in order to comply with STL exception
1040 safety requirements.
1042 @Note The implementation uses Boost.Typeof to automatically deduce the types of
1043 the captured variables.
1044 In order to compile code in type-of emulation mode, all types must be properly
1045 registered with Boost.Typeof (see the
1046 @RefSect{getting_started, Getting Started} section).
1048 @See @RefSect{tutorial, Tutorial} section,
1049 @RefSect{getting_started, Getting Started} section,
1050 @RefSect{no_variadic_macros, No Variadic Macros} section,
1051 @RefMacro{BOOST_SCOPE_EXIT_TPL}, @RefMacro{BOOST_SCOPE_EXIT_ALL},
1052 @RefMacro{BOOST_SCOPE_EXIT_END}, @RefMacro{BOOST_SCOPE_EXIT_ID}.
1054 #define BOOST_SCOPE_EXIT(capture_list)
1057 @brief This macro is a workaround for various versions of GCC to declare scope
1058 exits within templates.
1060 Various versions of the GCC compiler do not compile @RefMacro{BOOST_SCOPE_EXIT}
1061 inside function templates.
1062 As a workaround, @RefMacro{BOOST_SCOPE_EXIT_TPL} should be used instead of
1063 @RefMacro{BOOST_SCOPE_EXIT} in these cases:
1066 { // Some local scope.
1068 BOOST_SCOPE_EXIT_TPL(capture_list) {
1070 } BOOST_SCOPE_EXIT_END
1075 The syntax of @RefMacro{BOOST_SCOPE_EXIT_TPL} is the exact same as the one of
1076 @RefMacro{BOOST_SCOPE_EXIT} (see @RefMacro{BOOST_SCOPE_EXIT} for more
1079 On C++11 compilers, @RefMacro{BOOST_SCOPE_EXIT_TPL} is not needed because
1080 @RefMacro{BOOST_SCOPE_EXIT} always compiles on GCC versions that support C++11.
1081 However, @RefMacro{BOOST_SCOPE_EXIT_TPL} is still provided on C++11 so to write code that is portable between C++03 and C++11 compilers.
1082 It is recommended to always use @RefMacro{BOOST_SCOPE_EXIT_TPL} within
1083 templates so to maximize portability.
1085 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ID_TPL} must be used
1086 instead of @RefMacro{BOOST_SCOPE_EXIT_TPL} when it is necessary to expand
1087 multiple scope exit declarations on the same line within templates.
1089 @Note The issue in compiling scope exit declarations that some GCC versions
1090 have is illustrated by the following code (see also
1091 <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37920">GCC bug 37920</a>):
1094 void f(T const& x) {
1097 typedef __typeof__(i) typeof_i;
1098 typedef __typeof__(x) typeof_x;
1100 typedef local::typeof_i i_type;
1101 typedef local::typeof_x x_type;
1104 int main(void) { f(0); }
1106 This can be fixed by adding <c>typename</c> in front of <c>local::typeof_i</c>
1107 and <c>local::typeof_x</c> (which is the approach followed by the
1108 implementation of the @RefMacro{BOOST_SCOPE_EXIT_TPL} macro).
1110 @Note Although @RefMacro{BOOST_SCOPE_EXIT_TPL} has the same suffix as
1111 <c>BOOST_TYPEOF_TPL</c>, it does not follow the Boost.Typeof convention.
1113 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1114 @RefMacro{BOOST_SCOPE_EXIT_END}, @RefMacro{BOOST_SCOPE_EXIT_ID_TPL}.
1116 #define BOOST_SCOPE_EXIT_TPL(capture_list)
1119 @brief This macro allows to expand multiple scope exit declarations on the same
1122 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT} but it can be expanded
1123 multiple times on the same line if different identifiers <c>id</c> are provided
1124 for each expansion (see @RefMacro{BOOST_SCOPE_EXIT} for more information).
1128 A unique identifier token which can be concatenated by the preprocessor
1129 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1130 alphanumeric tokens\, etc).
1132 @Param{capture_list,
1133 Same as the <c>capture_list</c> parameter of the @RefMacro{BOOST_SCOPE_EXIT}
1138 @Note This macro can be useful when the scope exit macros are expanded
1139 within user-defined macros (because nested macros expand on the same line).
1140 On some compilers (e.g., MSVC which supports the non standard
1141 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1142 the use of this macro is always necessary to ensure portability when expanding
1143 multiple scope exit declarations on the same line.
1145 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1146 @RefMacro{BOOST_SCOPE_EXIT_END_ID}, @RefMacro{BOOST_SCOPE_EXIT_ALL_ID},
1147 @RefMacro{BOOST_SCOPE_EXIT_ID_TPL}.
1149 #define BOOST_SCOPE_EXIT_ID(id, capture_list)
1152 @brief This macro is required to expand multiple scope exit declarations on the
1153 same line within templates on various versions of GCC.
1155 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_TPL} but it can be
1156 expanded multiple times on the same line if different identifiers <c>id</c> are
1157 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_TPL} for more
1159 As with @RefMacro{BOOST_SCOPE_EXIT_TPL}, it is recommended to always use this
1160 macro when expanding scope exits multiple times on the same line within
1165 A unique identifier token which can be concatenated by the preprocessor
1166 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1167 alphanumeric tokens\, etc).
1169 @Param{capture_list,
1170 Same as the <c>capture_list</c> parameter of the
1171 @RefMacro{BOOST_SCOPE_EXIT_TPL} macro.
1175 @Note This macro can be useful when the scope exit macros are expanded
1176 within user-defined macros (because nested macros expand on the same line).
1177 On some compilers (e.g., MSVC which supports the non standard
1178 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1179 the use of this macro is always necessary to ensure portability when expanding
1180 multiple scope exit declarations on the same line.
1182 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT_TPL},
1183 @RefMacro{BOOST_SCOPE_EXIT_END_ID}, @RefMacro{BOOST_SCOPE_EXIT_ID},
1184 @RefMacro{BOOST_SCOPE_EXIT_ALL_ID}.
1186 #define BOOST_SCOPE_EXIT_ID_TPL(id, capture_list)
1189 @brief This macro declares a scope exit that captures all variables in scope
1192 This macro accepts a capture list starting with either <c>&</c> or <c>=</c> to capture all variables in scope by reference or value respectively (following the same syntax of C++11 lambdas).
1193 A part from that, this macro works like @RefMacro{BOOST_SCOPE_EXIT} (see @RefMacro{BOOST_SCOPE_EXIT} for more information):
1196 { // Some local scope.
1198 BOOST_SCOPE_EXIT_ALL(capture_list) { // C++11 only.
1200 }; // Use `;` instead of `BOOST_SCOPE_EXIT_END` (C++11 only).
1205 Note how the end of the scope exit body declared by this macro must be marked
1206 by a semi-column <c>;</c> (and not by @RefMacro{BOOST_SCOPE_EXIT_END}).
1208 @Warning This macro is only available on C++11 compilers (specifically, on
1209 C++11 compilers that do not define the Boost.Config <c>BOOST_NO_CXX11_LAMBDAS</c>
1211 It is not defined on non-C++11 compilers so its use on non-C++11 compilers will generate a compiler error.
1214 @Param{capture_list,
1215 On compilers that support variadic macros (see also Boost.Config
1216 <c>BOOST_NO_CXX11_VARIADIC_MACROS</c>)\, the capture list syntax is defined by the
1220 capture_tuple | capture_sequence
1222 {& | =} [\, capture\, capture\, ...]
1224 {(&) | (=)} [(capture) (capture) ...]
1228 On compilers that do not support variadic macros\, <c>capture_tuple</c> cannot
1232 void | capture_sequence
1234 Furthermore\, on C++11 compilers that support the use of <c>typename</c>
1235 outside templates\, also <c>this</c> can be used to capture the object at member
1239 [&]variable | this_ | this
1242 (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or
1243 <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing;
1244 <c>{expression}</c> means the token resulting from the expression.)
1248 Note that on compilers with variadic macro support (which should be all C++11
1249 compilers), the capture list can be specified as a comma-separated list.
1250 On all compilers, the same macro @RefMacro{BOOST_SCOPE_EXIT_ALL} also allows to
1251 specify the capture list as a Boost.Preprocessor sequence.
1253 The capture list must always contain at least the leading <c>&</c> or <c>=</c>
1254 so it can never be <c>void</c> (<c>BOOST_SCOPE_EXIT(void)</c> should be used
1255 to program scope exits with an empty capture list).
1257 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ALL_ID} must be used
1258 instead of @RefMacro{BOOST_SCOPE_EXIT_ALL} when it is necessary to expand
1259 multiple scope exit declarations on the same line.
1261 @Warning This macro capture list follows the exact same syntax of C++11 lambda
1262 captures which is unfortunately different from the syntax of
1263 @RefMacro{BOOST_SCOPE_EXIT} captures (unless programmers define the
1264 @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS} macro).
1265 For example, like C++11 lambda functions, @RefMacro{BOOST_SCOPE_EXIT_ALL}
1266 requires to capture data members by capturing the object <c>this</c> while
1267 @RefMacro{BOOST_SCOPE_EXIT} allows to capture data members directly and without
1268 capturing the object.
1270 @Warning The implementation executes the scope exit body within a destructor
1271 thus the scope exit body must never throw in order to comply with STL exception
1272 safety requirements.
1274 @Note This macro can always be used also within templates (so there is no need
1275 for a <c>BOOST_SCOPE_EXIT_ALL_TPL</c> macro).
1277 @See @RefSect{tutorial, Tutorial} section,
1278 @RefSect{no_variadic_macros, No Variadic Macros} section,
1279 @RefMacro{BOOST_SCOPE_EXIT}, @RefMacro{BOOST_SCOPE_EXIT_ALL_ID}.
1281 #define BOOST_SCOPE_EXIT_ALL(capture_list)
1284 @brief This macro allows to expand on the same line multiple scope exits that
1285 capture all variables in scope (C++11 only).
1287 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_ALL} but it can be
1288 expanded multiple times on the same line if different identifiers <c>id</c> are
1289 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_ALL} for more
1291 As with @RefMacro{BOOST_SCOPE_EXIT_ALL}, this macro is only available on C++11
1292 compilers (specifically, on C++11 compilers that do not define the
1293 Boost.Config <c>BOOST_NO_CXX11_LAMBDAS</c> macro).
1297 A unique identifier token which can be concatenated by the preprocessor
1298 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1299 alphanumeric tokens\, etc).
1301 @Param{capture_list,
1302 Same as the <c>capture_list</c> parameter of the
1303 @RefMacro{BOOST_SCOPE_EXIT_ALL} macro.
1307 @Note This macro can be useful when the scope exit macros are expanded
1308 within user-defined macros (because nested macros expand on the same line).
1309 On some compilers (e.g., MSVC which supports the non standard
1310 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1311 the use of this macro is always necessary to ensure portability when expanding
1312 multiple scope exit declarations on the same line.
1314 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT_ALL},
1315 @RefMacro{BOOST_SCOPE_EXIT_ID}.
1317 #define BOOST_SCOPE_EXIT_ALL_ID(id, capture_list)
1320 @brief This macro marks the end of a scope exit body.
1322 This macro must follow the closing curly bracket <c>}</c> that ends the body of
1323 either @RefMacro{BOOST_SCOPE_EXIT} or @RefMacro{BOOST_SCOPE_EXIT_TPL}:
1326 { // Some local scope.
1328 BOOST_SCOPE_EXIT(capture_list) {
1330 } BOOST_SCOPE_EXIT_END
1335 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_END_ID} must be used
1336 instead of @RefMacro{BOOST_SCOPE_EXIT_END} when it is necessary to expand
1337 multiple scope exit bodies on the same line.
1339 @Note If programmers define the @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS}
1340 macro on C++11 compilers, a semicolon <c>;</c> can be used instead of this
1342 However, to maximize portability, it is recommended to always use
1343 @RefMacro{BOOST_SCOPE_EXIT_END}.
1345 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1346 @RefMacro{BOOST_SCOPE_EXIT_TPL}, @RefMacro{BOOST_SCOPE_EXIT_END_ID}.
1348 #define BOOST_SCOPE_EXIT_END
1351 @brief This macro allows to terminate multiple scope exit bodies on the same
1354 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_END} but it can be
1355 expanded multiple times on the same line if different identifiers <c>id</c> are
1356 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_END} for more
1361 A unique identifier token which can be concatenated by the preprocessor
1362 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1363 alphanumeric tokens\, etc).
1367 @Note This macro can be useful when the scope exit macros are expanded
1368 within user-defined macros (because macros all expand on the same line).
1369 On some compilers (e.g., MSVC which supports the non standard
1370 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1371 the use of this macro is always necessary to ensure portability when expanding
1372 multiple scope exit macros on the same line (because this library can only
1373 portably use <c>__LINE__</c> to internally generate unique identifiers).
1375 @See @RefMacro{BOOST_SCOPE_EXIT_ID}, @RefMacro{BOOST_SCOPE_EXIT_ID_TPL},
1376 @RefMacro{BOOST_SCOPE_EXIT_END}.
1378 #define BOOST_SCOPE_EXIT_END_ID(id)
1381 @brief Force to use C++11 lambda functions to implement scope exits.
1383 If programmers define this configuration macro on a C++11 compiler for which
1384 the Boost.Config macro <c>BOOST_NO_CXX11_LAMBDAS</c> is not defined, the
1385 @RefMacro{BOOST_SCOPE_EXIT} and @RefMacro{BOOST_SCOPE_EXIT_TPL} macros will use
1386 C++11 lambda functions to declare scope exits.
1387 By default this macro is not defined.
1389 @Warning When scope exits are implemented using lambda functions, the syntax of
1390 the capture list follows the exact same syntax of C++11 lambda captures
1391 which is in general different from the legacy capture syntax of this library.
1392 For example, C++11 lambdas require to capture data members by capturing the
1393 object <c>this</c> while this library always allowed to capture data members
1395 Therefore, when this configuration macro is defined,
1396 @RefMacro{BOOST_SCOPE_EXIT} and @RefMacro{BOOST_SCOPE_EXIT_TPL} are no longer
1397 backward compatible (and this is why this macro is not defined by default).
1399 A semicolon <c>;</c> can be used instead of @RefMacro{BOOST_SCOPE_EXIT_END}
1400 when this configuration macro is defined (but it is recommended to always use
1401 @RefMacro{BOOST_SCOPE_EXIT_END} so to maximize portability).
1403 @Note This configuration macro does not control the definition of
1404 @RefMacro{BOOST_SCOPE_EXIT_ALL} which is always and automatically defined on
1405 compilers that support C++11 lambda functions.
1407 @See @RefMacro{BOOST_SCOPE_EXIT}, @RefMacro{BOOST_SCOPE_EXIT_TPL},
1408 @RefMacro{BOOST_SCOPE_EXIT_END}.
1410 #define BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS
1414 #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED