1
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
8
9 #ifndef BOOST_SCOPE_EXIT_HPP
10 #define BOOST_SCOPE_EXIT_HPP
11
12 #ifndef DOXYGEN
13
14 #include <boost/config/workaround.hpp>
15 #include <boost/type_traits/integral_constant.hpp>
16 #include <boost/type_traits/enable_if.hpp>
17 #include <boost/function.hpp>
18 #include <boost/typeof/typeof.hpp>
19 #include <boost/config.hpp>
20 #include <boost/preprocessor/cat.hpp>
21 #include <boost/preprocessor/control/iif.hpp>
22 #include <boost/preprocessor/control/expr_iif.hpp>
23 #include <boost/preprocessor/comparison/equal.hpp>
24 #include <boost/preprocessor/logical/bitor.hpp>
25 #include <boost/preprocessor/logical/bitand.hpp>
26 #include <boost/preprocessor/facilities/empty.hpp>
27 #include <boost/preprocessor/facilities/is_empty.hpp>
28 #include <boost/preprocessor/facilities/identity.hpp>
29 #include <boost/preprocessor/punctuation/comma_if.hpp>
30 #include <boost/preprocessor/punctuation/paren_if.hpp>
31 #include <boost/preprocessor/seq/cat.hpp>
32 #include <boost/preprocessor/seq/size.hpp>
33 #include <boost/preprocessor/seq/to_tuple.hpp>
34 #include <boost/preprocessor/tuple/elem.hpp>
35 #include <boost/preprocessor/tuple/eat.hpp>
36 #include <boost/preprocessor/tuple/to_list.hpp>
37 #include <boost/preprocessor/list/append.hpp>
38 #include <boost/preprocessor/list/fold_left.hpp>
39 #include <boost/preprocessor/list/enum.hpp>
40 #include <boost/preprocessor/list/adt.hpp>
41 #include <boost/preprocessor/list/for_each_i.hpp>
42 #include <boost/preprocessor/detail/is_unary.hpp>
43
44 // PRIVATE/PROTECTED //
45
46 // NOTE: AUX prefix and aux namespace mark "private" symbols that shall be used
47 // only within this library; DETAIL prefix and detail namespace mark "protected"
48 // symbols that can be used by other Boost libraries but not outside Boost.
49
50 // WARNING: BOOST_SCOPE_EXIT_AUX_GCC also used by some regression test.
51 #if defined(__GNUC__) && !defined(BOOST_INTEL)
52 # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
53 #else
54 # define BOOST_SCOPE_EXIT_AUX_GCC 0
55 #endif
56
57 #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
58 # define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 1
59 #else
60 # define BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01 0
61 #endif
62
63 #if BOOST_MSVC && (BOOST_MSVC <= 1900)
64 # define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 1
65 #else
66 # define BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01 0
67 #endif
68
69 // MSVC has problems expanding __LINE__ so use (the non standard) __COUNTER__.
70 #ifdef BOOST_MSVC
71 # define BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER __COUNTER__
72 #else
73 # define BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER __LINE__
74 #endif
75
76 // Preprocessor "keyword" detection.
77
78 // These are not a local macros, do not #undefine them (these are used by the
79 // ..._BACK macros below).
80 #define this_BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_THISUNDERSCORE_IS (1) /* unary */
81 #define void_BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_VOID_IS (1) /* unary */
82
83 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, checking_postfix) \
84 BOOST_PP_IS_UNARY(BOOST_PP_CAT(token, checking_postfix))
85
86 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_THISUNDERSCORE_BACK(token) \
87 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, \
88 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_THISUNDERSCORE_IS)
89
90 #define BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK(token) \
91 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_BACK_(token, \
92 _BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_VOID_IS)
93
94 // Preprocessor "void-list".
95
96 // NOTE: Empty list must always be represented as void (which is also a way to
97 // specify no function parameter) and it can never be empty because (1)
98 // IS_EMPTY(&var) fails (because of the leading non alphanumeric symbol) and
99 // (2) some compilers (MSVC) fail to correctly pass empty macro parameters
100 // even if they support variadic macros. Therefore, always using void to
101 // represent is more portable.
102
103 // Argument: (token1)...
104 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_SEQ_(unused, seq) \
105 BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), BOOST_PP_SEQ_TO_TUPLE(seq))
106
107 // Token: void | token1
108 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_VOID_( \
109 is_void_macro, token) \
110 BOOST_PP_IIF(is_void_macro(token), \
111 BOOST_PP_NIL \
112 , \
113 (token, BOOST_PP_NIL) \
114 )
115
116 // Token: (a)(b)... | empty | void | token
117 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_( \
118 is_void_macro, token) \
119 BOOST_PP_IIF(BOOST_PP_IS_UNARY(token), /* unary paren (a)... */ \
120 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_SEQ_ \
121 , \
122 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_VOID_ \
123 )(is_void_macro, token)
124
125 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_(tokens) \
126 0 /* void check always returns false */
127
128 #ifdef BOOST_NO_CXX11_VARIADIC_MACROS
129
130 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_(is_void_macro, seq) \
131 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_(is_void_macro, seq)
132
133 // Expand `void | (a)(b)...` to pp-list `NIL | (a, (b, NIL))`.
134 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(sign) \
135 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
136 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK, sign)
137
138 // Expand `(a)(b)...` to pp-list `(a, (b, NIL))`.
139 #define BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(seq) \
140 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
141 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_, seq)
142
143 #else // VARIADICS
144
145 // FUTURE: Replace this with BOOST_PP_VARIADIC_SIZE when and if
146 // BOOST_PP_VARIAIDCS detection will match !BOOST_NO_CXX11_VARIADIC_MACROS (for
147 // now Boost.Preprocessor and Boost.Config disagree on detecting compiler
148 // variadic support while this VARIADIC_SIZE works on compilers not detected by
149 // PP).
150 #if BOOST_MSVC
151 # define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_(...) \
152 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,),)
153 #else // MSVC
154 # define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_(...) \
155 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,)
156 #endif // MSVC
157 #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
158
159 // Argument: token1, ...
160 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_VARIADIC_(unused, ...) \
161 BOOST_PP_TUPLE_TO_LIST( \
162 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_( \
163 __VA_ARGS__), (__VA_ARGS__))
164
165 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_(is_void_macro, ...) \
166 BOOST_PP_IIF(BOOST_PP_EQUAL( \
167 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_VARIADIC_SIZE_( \
168 __VA_ARGS__), 1), \
169 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_HANDLE_SEQ_ \
170 , \
171 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_FROM_VARIADIC_ \
172 )(is_void_macro, __VA_ARGS__)
173
174 // Expand `void | (a)(b)... | a, b, ...` to pp-list `NIL | (a, (b, NIL))`.
175 #define BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(...) \
176 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
177 BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_VOID_BACK, __VA_ARGS__)
178
179 // Expand `(a)(b)... | a, b, ...` to pp-list `(a, (b, NIL))`.
180 #define BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(...) \
181 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_( \
182 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST_NEVER_, __VA_ARGS__)
183
184 #endif // VARIADICS
185
186 // Steven Watanabe's trick with a modification suggested by Kim Barrett
187 namespace boost { namespace scope_exit { namespace detail {
188
189 // Type of a local BOOST_SCOPE_EXIT_AUX_ARGS variable.
190 // First use in a local scope will declare the BOOST_SCOPE_EXIT_AUX_ARGS
191 // variable, subsequent uses will be resolved as two comparisons
192 // (cmp1 with 0 and cmp2 with BOOST_SCOPE_EXIT_AUX_ARGS).
193 template<int Dummy = 0>
194 struct declared
195 {
196 void* value;
197 static int const cmp2 = 0;
operator >(int,declared const &)198 friend void operator>(int, declared const&) {}
199 };
200
201 struct undeclared { declared<> dummy[2]; };
202
203 template<int> struct resolve;
204
205 template<>
206 struct resolve<sizeof(declared<>)>
207 {
208 static const int cmp1 = 0;
209 };
210
211 template<>
212 struct resolve<sizeof(undeclared)>
213 {
214 template<int>
215 struct cmp1
216 {
217 static int const cmp2 = 0;
218 };
219 };
220
221 typedef void (*ref_tag)(int&);
222 typedef void (*val_tag)(int );
223
224 template<class T, class Tag> struct member;
225
226 template<class T>
227 struct member<T,ref_tag>
228 {
229 T& value;
230 #if !BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
memberboost::scope_exit::detail::member231 member(T& ref) : value(ref) {}
232 #endif
233 };
234
235 template<class T>
236 struct member<T,val_tag>
237 {
238 T value;
239 #if !BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
memberboost::scope_exit::detail::member240 member(T& val) : value(val) {}
241 #endif
242 };
243
deref(T * p,ref_tag)244 template<class T> inline T& deref(T* p, ref_tag) { return *p; }
deref(T & r,val_tag)245 template<class T> inline T& deref(T& r, val_tag) { return r; }
246
247 template<class T>
248 struct wrapper
249 {
250 typedef T type;
251 };
252
253 template<class T> wrapper<T> wrap(T&);
254
255 } } } // namespace
256
257 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
258 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::detail::wrapper, 1)
259
260 #define BOOST_SCOPE_EXIT_AUX_ARGS boost_scope_exit_aux_args
261 extern boost::scope_exit::detail::undeclared BOOST_SCOPE_EXIT_AUX_ARGS;
262
263 #define BOOST_SCOPE_EXIT_AUX_GUARD(id) \
264 BOOST_PP_CAT(boost_se_guard_, id)
265
266 #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) \
267 BOOST_PP_CAT(boost_se_guard_t_, id)
268
269 #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) \
270 BOOST_PP_CAT(boost_se_params_, id)
271
272 #define BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
273 BOOST_PP_CAT(boost_se_this_t_, id)
274
275 #define BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id) \
276 BOOST_PP_CAT(boost_se_this_capture_t_, id)
277
278 #define BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) \
279 BOOST_PP_CAT(boost_se_params_t_, id)
280
281 #define BOOST_SCOPE_EXIT_DETAIL_TAG(id, i) \
282 BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
283
284 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) \
285 BOOST_PP_SEQ_CAT( (boost_se_param_this_)(id) )
286
287 #define BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var) \
288 BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
289
290 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var) \
291 BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
292
293 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(id, i, var) \
294 BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
295
296 #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
297 BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
298
299 #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
300 ::boost::scope_exit::detail::deref(var, \
301 static_cast<BOOST_SCOPE_EXIT_DETAIL_TAG(id, i)>(0))
302
303 #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
304 ::boost::scope_exit::detail::member< \
305 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var), \
306 BOOST_SCOPE_EXIT_DETAIL_TAG(id, i) \
307 > BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var);
308
309 #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, id_ty, i, var) \
310 BOOST_PP_COMMA_IF(i) \
311 BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
312 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty)):: \
313 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
314 i, var) \
315 var
316
317 #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) \
318 BOOST_PP_COMMA_IF(i) \
319 boost_se_params_->BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var).value
320
321 #define BOOST_SCOPE_EXIT_DETAIL_TAG_DECL(r, id, i, var) \
322 typedef void (*BOOST_SCOPE_EXIT_DETAIL_TAG(id, i))(int var);
323
324 // Adam Butcher's workaround to deduce `this` type on MSVC revision < 10.
325 // Boost.Typeof for VC71's typeid-based workaround does not work to determine
326 // `this` type due to error C2355 being incorrectly reported. The typical
327 // avoidance strategy implemented below is to make an indirect compile-time
328 // constant by assigning an enum and use that as type-index-- this only works
329 // with the sizeof() approach and not with the typeid() approach. Lorenzo
330 // Caminiti extended this approach to work in type-of emulation mode. This code
331 // is very similar (and somewhat of a duplication) of the code in
332 // boost/typeof/msvc/typeof_impl.hpp). However, this code cannot be integrated
333 // into Boost.Typeof because its final API has to be a `typedef ...` and it
334 // cannot be a `typeof(...)`.
335 #if BOOST_SCOPE_EXIT_AUX_TYPEOF_THIS_MSVC_WORKAROUND_01
336
337 #include <boost/config.hpp>
338 #include <boost/detail/workaround.hpp>
339 #include <boost/type_traits/integral_constant.hpp>
340 #include <boost/type_traits/is_function.hpp>
341 #include <boost/type_traits/enable_if.hpp>
342
343 #if defined(BOOST_MSVC)
344 # include <typeinfo>
345 #endif
346
347 namespace boost { namespace scope_exit { namespace aux {
348 namespace msvc_typeof_this {
349
350 // compile-time constant code
351 #if defined(BOOST_MSVC) && defined(_MSC_EXTENSIONS)
352
353 template<int N> struct the_counter;
354
355 template<typename T,int N = 5 /* for similarity */>
356 struct encode_counter {
__if_existsboost::scope_exit::aux::msvc_typeof_this::encode_counter357 __if_exists(the_counter<N + 256>) {
358 BOOST_STATIC_CONSTANT(unsigned,
359 count=(encode_counter<T,N + 257>::count));
360 }
__if_not_existsboost::scope_exit::aux::msvc_typeof_this::encode_counter361 __if_not_exists(the_counter<N + 256>) {
362 __if_exists(the_counter<N + 64>) {
363 BOOST_STATIC_CONSTANT(unsigned,
364 count=(encode_counter<T,N + 65>::count));
365 }
366 __if_not_exists(the_counter<N + 64>) {
367 __if_exists(the_counter<N + 16>) {
368 BOOST_STATIC_CONSTANT(unsigned,
369 count=(encode_counter<T,N + 17>::count));
370 }
371 __if_not_exists(the_counter<N + 16>) {
372 __if_exists(the_counter<N + 4>) {
373 BOOST_STATIC_CONSTANT(unsigned,
374 count=(encode_counter<T,N + 5>::count));
375 }
376 __if_not_exists(the_counter<N + 4>) {
377 __if_exists(the_counter<N>) {
378 BOOST_STATIC_CONSTANT(unsigned,
379 count=(encode_counter<T,N + 1>::count));
380 }
381 __if_not_exists(the_counter<N>) {
382 BOOST_STATIC_CONSTANT(unsigned,count=N);
383 typedef the_counter<N> type;
384 }
385 }
386 }
387 }
388 }
389 };
390
391 #else // compile-time constant code
392
393 template<int N> struct encode_counter : encode_counter<N - 1> {};
394
395 template<> struct encode_counter<0> {};
396
397 #endif // compile-time constant code
398
399 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) // type-of code
400
401 struct msvc_extract_type_default_param {};
402
403 template<typename ID, typename T = msvc_extract_type_default_param>
404 struct msvc_extract_type;
405
406 template<typename ID>
407 struct msvc_extract_type<ID, msvc_extract_type_default_param> {
408 template<bool>
409 struct id2type_impl;
410
411 typedef id2type_impl<true> id2type;
412 };
413
414 template<typename ID, typename T>
415 struct msvc_extract_type
416 : msvc_extract_type<ID, msvc_extract_type_default_param> {
417 template<>
418 struct id2type_impl<true> { // VC8.0 specific bug-feature.
419 typedef T type;
420 };
421
422 template<bool>
423 struct id2type_impl;
424
425 typedef id2type_impl<true> id2type;
426 };
427
428 template<typename T, typename ID>
429 struct msvc_register_type : msvc_extract_type<ID, T> {};
430
431 #else // type-of code
432
433 template<typename ID>
434 struct msvc_extract_type {
435 struct id2type;
436 };
437
438 template<typename T, typename ID>
439 struct msvc_register_type : msvc_extract_type<ID> {
440 typedef msvc_extract_type<ID> base_type;
441 struct base_type::id2type { // This uses nice VC6.5 and VC7.1 bug-features.
442 typedef T type;
443 };
444 };
445
446 #endif // typeof code
447
448 template<int Id>
449 struct msvc_typeid_wrapper {
450 typedef typename msvc_extract_type<boost::integral_constant<int, Id>
451 >::id2type id2type;
452 typedef typename id2type::type type;
453 };
454
455 template<>
456 struct msvc_typeid_wrapper<4> {
457 typedef msvc_typeid_wrapper<4> type;
458 };
459
460 template<typename T>
461 struct encode_type {
462 BOOST_STATIC_CONSTANT(unsigned, value = encode_counter<T>::count);
463 typedef typename msvc_register_type<T,
464 boost::integral_constant<int, value> >::id2type type;
465 BOOST_STATIC_CONSTANT(unsigned, next = value + 1);
466 };
467
468 template<class T>
469 struct sizer {
470 typedef char(*type)[encode_type<T>::value];
471 };
472
473 template<typename T>
474 typename boost::enable_if_<
475 !boost::is_function<T>::value
476 , typename sizer<T>::type
477 >::type encode_start(T const&);
478
479 template<typename T>
480 typename boost::enable_if_<
481 boost::is_function<T>::value
482 , typename sizer<T>::type
483 >::type encode_start(T&);
484
485 template<typename Organizer, typename T>
486 msvc_register_type<T, Organizer> typeof_register_type(const T&,
487 Organizer* = 0);
488
489 } } } } // namespace
490
491 #define BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
492 BOOST_PP_CAT(boost_se_thistype_index_, id)
493
494 #define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, new_type) \
495 /* unfortunately, we need to go via this enum which causes this to be */ \
496 /* a typedef construct and not a typeof (so this code cannot be */ \
497 /* integrated into Boost.Typeof) */ \
498 enum { \
499 BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) = sizeof( \
500 *::boost::scope_exit::aux::msvc_typeof_this::encode_start(this)) \
501 }; \
502 typedef \
503 ty ::boost::scope_exit::aux::msvc_typeof_this::msvc_typeid_wrapper< \
504 BOOST_SCOPE_EXIT_AUX_TYPEDEF_TYPEOF_THIS_INDEX_(id) \
505 >::type \
506 new_type \
507 ;
508
509 #else // TYPEOF_THIS_MSVC_WORKAROUND
510
511 #define BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, new_type) \
512 typedef /* trailing `EMPTY()` handles empty `ty` */ \
513 BOOST_PP_IIF(BOOST_PP_IS_EMPTY(ty BOOST_PP_EMPTY()), \
514 BOOST_TYPEOF \
515 , \
516 BOOST_TYPEOF_TPL \
517 )(this) \
518 new_type \
519 ;
520
521 #endif // TYPEOF_THIS_MSVC_WORKAROUND
522
523 #if BOOST_SCOPE_EXIT_AUX_TPL_GCC_WORKAROUND_01
524
525 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, captures, has_this) \
526 /* expand to nothing */
527
528 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT(r, id, i, var) \
529 BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) }
530
531 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, captures, has_this) \
532 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(has_this, \
533 BOOST_PP_LIST_IS_CONS(captures)), \
534 = { \
535 ) \
536 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT, id, captures) \
537 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS(captures), \
538 has_this)) \
539 BOOST_PP_EXPR_IIF(has_this, this) /* no extra {...} needed here */ \
540 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(has_this, \
541 BOOST_PP_LIST_IS_CONS(captures)), \
542 } /* trailing `;` will be added by the caller */ \
543 )
544
545 #else // TPL_GCC_WORKAROUND
546
547 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) \
548 BOOST_PP_COMMA_IF(i) \
549 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var) & BOOST_PP_CAT(a, i)
550
551 #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) \
552 BOOST_PP_COMMA_IF(i) \
553 BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var) ( BOOST_PP_CAT(a, i) )
554
555 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id) \
556 BOOST_PP_CAT(boost_se_this_arg_, id)
557
558 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS(id, ty, comma01) \
559 BOOST_PP_COMMA_IF(comma01) \
560 ty BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)::BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
561 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id) /* ptr so no & */
562
563 #define BOOST_SCOPE_EXIT_AUX_MEMBER_THIS_INIT(id, comma01) \
564 BOOST_PP_COMMA_IF(comma01) \
565 BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id)( \
566 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS_NAME(id))
567
568 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, captures, has_this) \
569 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)( \
570 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, captures) \
571 BOOST_PP_IIF(has_this, \
572 BOOST_SCOPE_EXIT_AUX_CTOR_ARG_THIS \
573 , \
574 BOOST_PP_TUPLE_EAT(3) \
575 )(id, ty, BOOST_PP_LIST_IS_CONS(captures)) \
576 ) \
577 BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(BOOST_PP_LIST_IS_CONS(captures), \
578 has_this), \
579 : \
580 ) \
581 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, \
582 captures) \
583 BOOST_PP_IIF(has_this, \
584 BOOST_SCOPE_EXIT_AUX_MEMBER_THIS_INIT \
585 , \
586 BOOST_PP_TUPLE_EAT(2) \
587 )(id, BOOST_PP_LIST_IS_CONS(captures)) \
588 {}
589
590 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT(r, id, i, var) \
591 BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
592
593 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, captures, has_this) \
594 BOOST_PP_LPAREN_IF(BOOST_PP_BITOR(has_this, \
595 BOOST_PP_LIST_IS_CONS(captures))) \
596 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT, id, captures) \
597 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS(captures), \
598 has_this)) \
599 BOOST_PP_EXPR_IIF(has_this, this) \
600 BOOST_PP_RPAREN_IF(BOOST_PP_BITOR(has_this, \
601 BOOST_PP_LIST_IS_CONS(captures)))
602
603 #endif // TPL_GCC_WORKAROUND
604
605 #if defined(BOOST_TYPEOF_EMULATION)
606
607 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
608 struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i) \
609 /* no need to use TYPEOF_TPL here because it's within inheritance */ \
610 : BOOST_TYPEOF(::boost::scope_exit::detail::wrap( \
611 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
612 i, var))) \
613 {}; \
614 typedef BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
615 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i)::type\
616 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
617 i, var) \
618 ;
619
620 #elif defined(BOOST_INTEL)
621
622 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
623 typedef \
624 /* no TYPEOF_TPL here because uses TYPEOF_KEYWORD directly */ \
625 BOOST_TYPEOF_KEYWORD(BOOST_SCOPE_EXIT_AUX_DEREF( \
626 BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i, var)) \
627 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
628 i, var) \
629 ;
630
631 #else
632
633 #define BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, id_ty, i, var) \
634 typedef \
635 /* no need to use TYPEOF_TPL here because it's a typedef */ \
636 BOOST_TYPEOF(::boost::scope_exit::detail::wrap( \
637 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
638 i, var))) \
639 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i) \
640 ; \
641 typedef BOOST_PP_TUPLE_ELEM(2, 1, id_ty) \
642 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), i)::type\
643 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
644 i, var) \
645 ;
646
647 #endif
648
649 #define BOOST_SCOPE_EXIT_DETAIL_PARAM_DECL(r, id_ty, i, var) \
650 typedef \
651 BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
652 i, var) \
653 BOOST_SCOPE_EXIT_DETAIL_PARAM_T(BOOST_PP_TUPLE_ELEM(2, 0, id_ty), \
654 i, var) \
655 ;
656
657 // Traits.
658
659 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP_CAPTURE(d, captures, this01, capture) \
660 (BOOST_PP_LIST_APPEND(captures, (capture, BOOST_PP_NIL)), this01)
661
662 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP_THIS(d, captures, this01, this_) \
663 (captures, 1 /* has this (note, no error if multiple this_) */)
664
665 #define BOOST_SCOPE_EXIT_AUX_TRAITS_OP(d, captures_this, capture) \
666 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_PP_KEYWORD_IS_THISUNDERSCORE_BACK(\
667 capture), \
668 BOOST_SCOPE_EXIT_AUX_TRAITS_OP_THIS \
669 , \
670 BOOST_SCOPE_EXIT_AUX_TRAITS_OP_CAPTURE \
671 )(d, BOOST_PP_TUPLE_ELEM(2, 0, captures_this), \
672 BOOST_PP_TUPLE_ELEM(2, 1, captures_this), capture)
673
674 // ref_val: & | =
675 #define BOOST_SCOPE_EXIT_AUX_TRAITS_ALL_OP(ref_val, traits) \
676 ( \
677 BOOST_PP_LIST_APPEND((ref_val, BOOST_PP_NIL), \
678 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
679 , \
680 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits) \
681 )
682
683 #define BOOST_SCOPE_EXIT_AUX_TRAITS(captures) \
684 BOOST_PP_LIST_FOLD_LEFT(BOOST_SCOPE_EXIT_AUX_TRAITS_OP, \
685 (BOOST_PP_NIL, 0), captures)
686
687 #define BOOST_SCOPE_EXIT_AUX_TRAITS_ALL(captures) \
688 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL_OP(BOOST_PP_LIST_FIRST(captures), \
689 BOOST_SCOPE_EXIT_AUX_TRAITS(BOOST_PP_LIST_REST(captures)))
690
691 #define BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits) \
692 BOOST_PP_TUPLE_ELEM(2, 0, traits)
693
694 #define BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits) \
695 BOOST_PP_TUPLE_ELEM(2, 1, traits)
696
697 #ifndef BOOST_NO_CXX11_LAMBDAS
698
699 namespace boost { namespace scope_exit { namespace aux {
700
701 template<typename This = void>
702 struct guard { // With object `this_` (for backward compatibility).
guardboost::scope_exit::aux::guard703 explicit guard(This _this) : this_(_this) {}
~guardboost::scope_exit::aux::guard704 ~guard() { if(f_) f_(this_); }
705 template<typename Lambda>
operator =boost::scope_exit::aux::guard706 void operator=(Lambda f) { f_ = f; }
707 private:
708 This this_;
709 boost::function<void (This)> f_;
710 };
711
712 template<>
713 struct guard<void> { // Without object `this_` (could capture `this` directly).
~guardboost::scope_exit::aux::guard714 ~guard() { if(f_) f_(); }
715 template<typename Lambda>
operator =boost::scope_exit::aux::guard716 void operator=(Lambda f) { f_ = f; }
717 private:
718 boost::function<void (void)> f_;
719 };
720
721 } } } // namespace
722
723 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id) \
724 BOOST_PP_CAT(boost_se_lambda_params_, id)
725
726 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id) \
727 BOOST_PP_CAT(boost_se_lambda_this_t_, id)
728
729 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id) \
730 BOOST_PP_CAT(boost_se_lambda_this_capture_t_, id)
731
732 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE(id, ty) \
733 ty BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id):: \
734 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id)
735
736 // Precondition: HAS_THIS(traits).
737 #define BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPEDEFS(id, ty, traits) \
738 BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, ty, \
739 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id)) \
740 /* capture type for workaround GCC internal error (even on later C++11) */ \
741 struct BOOST_SCOPE_EXIT_AUX_LAMBDA_PARAMS(id) { \
742 typedef BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_CAPTURE_TYPE(id) \
743 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_PARAM_TYPE(id); \
744 };
745
746 #define BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, ty, traits) \
747 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
748 /* no need for TYPEDEF THIS MSVC workaround on C++11 */ \
749 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPEDEFS \
750 , \
751 BOOST_PP_TUPLE_EAT(3) \
752 )(id, ty, traits) \
753 ::boost::scope_exit::aux::guard< \
754 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
755 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE \
756 , \
757 BOOST_PP_TUPLE_EAT(2) \
758 )(id, ty) \
759 > BOOST_SCOPE_EXIT_AUX_GUARD(id) \
760 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
761 (this) \
762 ) \
763 ; \
764 BOOST_SCOPE_EXIT_AUX_GUARD(id) = [ \
765 BOOST_PP_LIST_ENUM(BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
766 ]( \
767 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
768 BOOST_SCOPE_EXIT_AUX_LAMBDA_THIS_TYPE \
769 , \
770 BOOST_PP_TUPLE_EAT(2) \
771 )(id, ty) \
772 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), this_) \
773 ) mutable /* can change value captures (as with SCOPE_EXIT) */ -> void
774
775 #endif // Lambdas.
776
777 #if defined(BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS) && \
778 !defined(BOOST_NO_CXX11_LAMBDAS) // Use lambda for SCOPE_EXIT (not just _ALL).
779
780 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, ty, traits) \
781 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, ty, traits)
782
783 #else // Not using lambdas.
784
785 // ty: EMPTY() | typename
786 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, ty, traits) \
787 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_TAG_DECL, id, \
788 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
789 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL, (id, ty), \
790 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
791 BOOST_PP_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
792 BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS \
793 , \
794 BOOST_PP_TUPLE_EAT(3) \
795 )(id, ty, BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id)) \
796 struct BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) { \
797 /* interim capture types to workaround internal errors on old GCC */ \
798 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_DETAIL_PARAM_DECL, (id, ty), \
799 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
800 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
801 typedef BOOST_SCOPE_EXIT_AUX_THIS_CAPTURE_T(id) \
802 BOOST_SCOPE_EXIT_AUX_THIS_T(id) ; \
803 ) \
804 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, \
805 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
806 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
807 BOOST_SCOPE_EXIT_AUX_THIS_T(id) \
808 BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) ; \
809 ) \
810 BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, ty, \
811 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits), \
812 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits)) \
813 } BOOST_SCOPE_EXIT_AUX_PARAMS(id) \
814 BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, \
815 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits), \
816 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits)) \
817 ; \
818 ::boost::scope_exit::detail::declared< \
819 ::boost::scope_exit::detail::resolve< \
820 sizeof(BOOST_SCOPE_EXIT_AUX_ARGS) \
821 >::cmp1<0>::cmp2 \
822 > BOOST_SCOPE_EXIT_AUX_ARGS; \
823 BOOST_SCOPE_EXIT_AUX_ARGS.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
824 struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
825 BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)* boost_se_params_; \
826 BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
827 : boost_se_params_( \
828 (BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id)*)boost_se_params) \
829 {} \
830 ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { \
831 boost_se_body( \
832 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, \
833 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
834 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS( \
835 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)), \
836 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits))) \
837 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS( \
838 traits), \
839 boost_se_params_->BOOST_SCOPE_EXIT_DETAIL_PARAM_THIS(id) \
840 ) \
841 ); \
842 } \
843 static void boost_se_body( \
844 BOOST_PP_LIST_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id, ty), \
845 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)) \
846 BOOST_PP_COMMA_IF(BOOST_PP_BITAND(BOOST_PP_LIST_IS_CONS( \
847 BOOST_SCOPE_EXIT_AUX_TRAITS_CAPTURES(traits)), \
848 BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits))) \
849 BOOST_PP_EXPR_IIF(BOOST_SCOPE_EXIT_AUX_TRAITS_HAS_THIS(traits), \
850 ty BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id):: \
851 BOOST_SCOPE_EXIT_AUX_THIS_T(id) this_ \
852 ) \
853 )
854
855 #endif // Using lambdas.
856
857 // PUBLIC //
858
859 #if defined(BOOST_NO_CXX11_VARIADIC_MACROS) // No variadic macros (sequences only).
860 # define BOOST_SCOPE_EXIT_ID(id, void_or_seq) \
861 BOOST_SCOPE_EXIT_AUX_IMPL(id, BOOST_PP_EMPTY(), \
862 BOOST_SCOPE_EXIT_AUX_TRAITS( \
863 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(void_or_seq)))
864 # define BOOST_SCOPE_EXIT_ID_TPL(id, void_or_seq) \
865 BOOST_SCOPE_EXIT_AUX_IMPL(id, typename, \
866 BOOST_SCOPE_EXIT_AUX_TRAITS( \
867 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(void_or_seq)))
868 # define BOOST_SCOPE_EXIT(void_or_seq) \
869 BOOST_SCOPE_EXIT_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
870 void_or_seq)
871 # define BOOST_SCOPE_EXIT_TPL(void_or_seq) \
872 BOOST_SCOPE_EXIT_ID_TPL(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
873 void_or_seq)
874 # if !defined(BOOST_NO_CXX11_LAMBDAS)
875 # define BOOST_SCOPE_EXIT_ALL_ID(id, seq) \
876 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, \
877 /* C++11 allows to use typename outside templates so */ \
878 /* always typename here and no need for ..._ALL_TPL */ \
879 /* (if a C++11 compiler does not implement this use of */ \
880 /* typename, always use `this` instead of `this_`) */ \
881 typename, \
882 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL( \
883 BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST(seq)))
884 # define BOOST_SCOPE_EXIT_ALL(seq) \
885 BOOST_SCOPE_EXIT_ALL_ID( \
886 BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, seq)
887 # endif
888 #else // Variadic macros (both sequences and variadic tuples).
889 # define BOOST_SCOPE_EXIT_ID(id, ...) \
890 BOOST_SCOPE_EXIT_AUX_IMPL(id, BOOST_PP_EMPTY(), \
891 BOOST_SCOPE_EXIT_AUX_TRAITS( \
892 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(__VA_ARGS__)))
893 # define BOOST_SCOPE_EXIT_ID_TPL(id, ...) \
894 BOOST_SCOPE_EXIT_AUX_IMPL(id, typename, \
895 BOOST_SCOPE_EXIT_AUX_TRAITS( \
896 BOOST_SCOPE_EXIT_AUX_PP_VOID_LIST(__VA_ARGS__)))
897 # define BOOST_SCOPE_EXIT(...) \
898 BOOST_SCOPE_EXIT_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
899 __VA_ARGS__)
900 # define BOOST_SCOPE_EXIT_TPL(...) \
901 BOOST_SCOPE_EXIT_ID_TPL(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, \
902 __VA_ARGS__)
903 # if !defined(BOOST_NO_CXX11_LAMBDAS)
904 # define BOOST_SCOPE_EXIT_ALL_ID(id, ...) \
905 BOOST_SCOPE_EXIT_AUX_IMPL_LAMBDA(id, \
906 /* C++11 allows to use typename outside templates so */ \
907 /* always typename here and no need for ..._ALL_TPL */ \
908 /* (if a C++11 compiler does not implement this use of */ \
909 /* typename, always use `this` instead of `this_`) */ \
910 typename, \
911 BOOST_SCOPE_EXIT_AUX_TRAITS_ALL( \
912 BOOST_SCOPE_EXIT_AUX_PP_NON_VOID_LIST( \
913 __VA_ARGS__)))
914 # define BOOST_SCOPE_EXIT_ALL(...) \
915 BOOST_SCOPE_EXIT_ALL_ID( \
916 BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER, __VA_ARGS__)
917 # endif
918 #endif // Variadics.
919
920 #if defined(BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS) && \
921 !defined(BOOST_NO_CXX11_LAMBDAS) // Use lambdas for SCOPE_EXIT (not just ALL).
922 # define BOOST_SCOPE_EXIT_END_ID(id) \
923 ; /* lambdas ended with just `;` */
924 #else // Not using lambdas.
925 # define BOOST_SCOPE_EXIT_END_ID(id) \
926 } BOOST_SCOPE_EXIT_AUX_GUARD(id)(BOOST_SCOPE_EXIT_AUX_ARGS.value);
927 #endif // Using lambdas.
928 #define BOOST_SCOPE_EXIT_END \
929 BOOST_SCOPE_EXIT_END_ID(BOOST_SCOPE_EXIT_AUX_PP_LINE_COUNTER)
930
931 // DOCUMENTATION //
932
933 #else // DOXYGEN
934
935 /** @file
936 @brief Scope exits allow to execute arbitrary code when the enclosing scope
937 exits.
938 */
939
940 /**
941 @brief This macro declares a scope exit.
942
943 The scope exit declaration schedules the execution of the scope exit body at
944 the exit of the enclosing scope:
945
946 @code
947 { // Some local scope.
948 ...
949 BOOST_SCOPE_EXIT(capture_list) {
950 ... // Body code.
951 } BOOST_SCOPE_EXIT_END
952 ...
953 }
954 @endcode
955
956 The enclosing scope must be local.
957 If multiple scope exits are declared within the same enclosing scope, the scope
958 exit bodies are executed in the reversed order of their declarations.
959 Note how the end of the scope exit body must be marked by
960 @RefMacro{BOOST_SCOPE_EXIT_END}.
961
962 @Params
963 @Param{capture_list,
964 On compilers that support variadic macros (see also Boost.Config
965 <c>BOOST_NO_CXX11_VARIADIC_MACROS</c>)\, the capture list syntax is defined by the
966 following grammar:
967 @code
968 capture_list:
969 void | capture_tuple | capture_sequence
970 capture_tuple:
971 capture\, capture\, ...
972 capture_sequence:
973 (capture) (capture) ...
974 capture:
975 [&]variable | this_
976 @endcode
977 On compilers that do not support variadic macros\, <c>capture_tuple</c> cannot
978 be used:
979 @code
980 capture_list:
981 void | capture_sequence
982 @endcode
983 Furthermore\, if @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS} is defined on
984 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
985 @RefMacro{BOOST_SCOPE_EXIT_END} and <c>this</c> can be used instead of
986 <c>this_</c>:
987 @code
988 capture:
989 [&]variable | this_ | this
990 @endcode
991
992 (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or
993 <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing;
994 <c>{expression}</c> means the tokens resulting from the expression.)
995 }
996 @EndParams
997
998 Note that on compilers that support variadic macros (most of moder compliers
999 and all C++11 compilers), the capture list can be specified as a
1000 comma-separated list of tokens (this is the preferred syntax).
1001 However, on all compilers the same macro @RefMacro{BOOST_SCOPE_EXIT} also
1002 allows to specify the capture list as a Boost.Preprocessor sequence of tokens
1003 (for supporting compilers without variadic macros and for backward compatibility with older versions of this library).
1004
1005 The name <c>variable</c> of each captured variable must be a valid name in the
1006 enclosing scope and it must appear exactly once in the capture list.
1007 If a capture starts with the ampersand sign <c>&</c>, the corresponding
1008 variable will be available by reference within the scope exit body; otherwise,
1009 a copy of the variable will be made at the point of the scope exit declaration
1010 and that copy will be available inside the scope exit body (in this case, the
1011 variable's type must be <c>CopyConstructible</c>).
1012
1013 From within a member function, the object <c>this</c> can be captured using the
1014 special name <c>this_</c> in both the capture list and the scope exit body
1015 (using <c>this</c> instead of <c>this_</c> in the scope exit body leads to
1016 undefined behaviour).
1017
1018 It is possible to capture no variable by specifying the capture list as
1019 <c>void</c> (regardless of variadic macro support).
1020
1021 Only variables listed in the capture list, static variables, <c>extern</c>
1022 variables, global variables, functions, and enumerations from the enclosing
1023 scope can be used inside the scope exit body.
1024
1025 On various GCC versions the special macro @RefMacro{BOOST_SCOPE_EXIT_TPL} must
1026 be used instead of @RefMacro{BOOST_SCOPE_EXIT} within templates (to maximize
1027 portability, it is recommended to always use @RefMacro{BOOST_SCOPE_EXIT_TPL}
1028 within templates).
1029
1030 On C++11, it is possible capture all variables in scope without listing their
1031 names one-by-one using the macro @RefMacro{BOOST_SCOPE_EXIT_ALL}.
1032
1033 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ID} must be used
1034 instead of @RefMacro{BOOST_SCOPE_EXIT} when it is necessary to expand multiple
1035 scope exit declarations on the same line.
1036
1037 @Warning The implementation executes the scope exit body within a destructor
1038 thus the scope exit body must never throw in order to comply with STL exception
1039 safety requirements.
1040
1041 @Note The implementation uses Boost.Typeof to automatically deduce the types of
1042 the captured variables.
1043 In order to compile code in type-of emulation mode, all types must be properly
1044 registered with Boost.Typeof (see the
1045 @RefSect{getting_started, Getting Started} section).
1046
1047 @See @RefSect{tutorial, Tutorial} section,
1048 @RefSect{getting_started, Getting Started} section,
1049 @RefSect{no_variadic_macros, No Variadic Macros} section,
1050 @RefMacro{BOOST_SCOPE_EXIT_TPL}, @RefMacro{BOOST_SCOPE_EXIT_ALL},
1051 @RefMacro{BOOST_SCOPE_EXIT_END}, @RefMacro{BOOST_SCOPE_EXIT_ID}.
1052 */
1053 #define BOOST_SCOPE_EXIT(capture_list)
1054
1055 /**
1056 @brief This macro is a workaround for various versions of GCC to declare scope
1057 exits within templates.
1058
1059 Various versions of the GCC compiler do not compile @RefMacro{BOOST_SCOPE_EXIT}
1060 inside function templates.
1061 As a workaround, @RefMacro{BOOST_SCOPE_EXIT_TPL} should be used instead of
1062 @RefMacro{BOOST_SCOPE_EXIT} in these cases:
1063
1064 @code
1065 { // Some local scope.
1066 ...
1067 BOOST_SCOPE_EXIT_TPL(capture_list) {
1068 ... // Body code.
1069 } BOOST_SCOPE_EXIT_END
1070 ...
1071 }
1072 @endcode
1073
1074 The syntax of @RefMacro{BOOST_SCOPE_EXIT_TPL} is the exact same as the one of
1075 @RefMacro{BOOST_SCOPE_EXIT} (see @RefMacro{BOOST_SCOPE_EXIT} for more
1076 information).
1077
1078 On C++11 compilers, @RefMacro{BOOST_SCOPE_EXIT_TPL} is not needed because
1079 @RefMacro{BOOST_SCOPE_EXIT} always compiles on GCC versions that support C++11.
1080 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.
1081 It is recommended to always use @RefMacro{BOOST_SCOPE_EXIT_TPL} within
1082 templates so to maximize portability.
1083
1084 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ID_TPL} must be used
1085 instead of @RefMacro{BOOST_SCOPE_EXIT_TPL} when it is necessary to expand
1086 multiple scope exit declarations on the same line within templates.
1087
1088 @Note The issue in compiling scope exit declarations that some GCC versions
1089 have is illustrated by the following code (see also
1090 <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37920">GCC bug 37920</a>):
1091 @code
1092 template<class T>
1093 void f(T const& x) {
1094 int i = 0;
1095 struct local {
1096 typedef __typeof__(i) typeof_i;
1097 typedef __typeof__(x) typeof_x;
1098 };
1099 typedef local::typeof_i i_type;
1100 typedef local::typeof_x x_type;
1101 }
1102
1103 int main(void) { f(0); }
1104 @endcode
1105 This can be fixed by adding <c>typename</c> in front of <c>local::typeof_i</c>
1106 and <c>local::typeof_x</c> (which is the approach followed by the
1107 implementation of the @RefMacro{BOOST_SCOPE_EXIT_TPL} macro).
1108
1109 @Note Although @RefMacro{BOOST_SCOPE_EXIT_TPL} has the same suffix as
1110 <c>BOOST_TYPEOF_TPL</c>, it does not follow the Boost.Typeof convention.
1111
1112 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1113 @RefMacro{BOOST_SCOPE_EXIT_END}, @RefMacro{BOOST_SCOPE_EXIT_ID_TPL}.
1114 */
1115 #define BOOST_SCOPE_EXIT_TPL(capture_list)
1116
1117 /**
1118 @brief This macro allows to expand multiple scope exit declarations on the same
1119 line.
1120
1121 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT} but it can be expanded
1122 multiple times on the same line if different identifiers <c>id</c> are provided
1123 for each expansion (see @RefMacro{BOOST_SCOPE_EXIT} for more information).
1124
1125 @Params
1126 @Param{id,
1127 A unique identifier token which can be concatenated by the preprocessor
1128 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1129 alphanumeric tokens\, etc).
1130 }
1131 @Param{capture_list,
1132 Same as the <c>capture_list</c> parameter of the @RefMacro{BOOST_SCOPE_EXIT}
1133 macro.
1134 }
1135 @EndParams
1136
1137 @Note This macro can be useful when the scope exit macros are expanded
1138 within user-defined macros (because nested macros expand on the same line).
1139 On some compilers (e.g., MSVC which supports the non standard
1140 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1141 the use of this macro is always necessary to ensure portability when expanding
1142 multiple scope exit declarations on the same line.
1143
1144 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1145 @RefMacro{BOOST_SCOPE_EXIT_END_ID}, @RefMacro{BOOST_SCOPE_EXIT_ALL_ID},
1146 @RefMacro{BOOST_SCOPE_EXIT_ID_TPL}.
1147 */
1148 #define BOOST_SCOPE_EXIT_ID(id, capture_list)
1149
1150 /**
1151 @brief This macro is required to expand multiple scope exit declarations on the
1152 same line within templates on various versions of GCC.
1153
1154 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_TPL} but it can be
1155 expanded multiple times on the same line if different identifiers <c>id</c> are
1156 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_TPL} for more
1157 information).
1158 As with @RefMacro{BOOST_SCOPE_EXIT_TPL}, it is recommended to always use this
1159 macro when expanding scope exits multiple times on the same line within
1160 templates.
1161
1162 @Params
1163 @Param{id,
1164 A unique identifier token which can be concatenated by the preprocessor
1165 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1166 alphanumeric tokens\, etc).
1167 }
1168 @Param{capture_list,
1169 Same as the <c>capture_list</c> parameter of the
1170 @RefMacro{BOOST_SCOPE_EXIT_TPL} macro.
1171 }
1172 @EndParams
1173
1174 @Note This macro can be useful when the scope exit macros are expanded
1175 within user-defined macros (because nested macros expand on the same line).
1176 On some compilers (e.g., MSVC which supports the non standard
1177 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1178 the use of this macro is always necessary to ensure portability when expanding
1179 multiple scope exit declarations on the same line.
1180
1181 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT_TPL},
1182 @RefMacro{BOOST_SCOPE_EXIT_END_ID}, @RefMacro{BOOST_SCOPE_EXIT_ID},
1183 @RefMacro{BOOST_SCOPE_EXIT_ALL_ID}.
1184 */
1185 #define BOOST_SCOPE_EXIT_ID_TPL(id, capture_list)
1186
1187 /**
1188 @brief This macro declares a scope exit that captures all variables in scope
1189 (C++11 only).
1190
1191 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).
1192 A part from that, this macro works like @RefMacro{BOOST_SCOPE_EXIT} (see @RefMacro{BOOST_SCOPE_EXIT} for more information):
1193
1194 @code
1195 { // Some local scope.
1196 ...
1197 BOOST_SCOPE_EXIT_ALL(capture_list) { // C++11 only.
1198 ... // Body code.
1199 }; // Use `;` instead of `BOOST_SCOPE_EXIT_END` (C++11 only).
1200 ...
1201 }
1202 @endcode
1203
1204 Note how the end of the scope exit body declared by this macro must be marked
1205 by a semi-column <c>;</c> (and not by @RefMacro{BOOST_SCOPE_EXIT_END}).
1206
1207 @Warning This macro is only available on C++11 compilers (specifically, on
1208 C++11 compilers that do not define the Boost.Config <c>BOOST_NO_CXX11_LAMBDAS</c>
1209 macro).
1210 It is not defined on non-C++11 compilers so its use on non-C++11 compilers will generate a compiler error.
1211
1212 @Params
1213 @Param{capture_list,
1214 On compilers that support variadic macros (see also Boost.Config
1215 <c>BOOST_NO_CXX11_VARIADIC_MACROS</c>)\, the capture list syntax is defined by the
1216 following grammar:
1217 @code
1218 capture_list:
1219 capture_tuple | capture_sequence
1220 capture_tuple:
1221 {& | =} [\, capture\, capture\, ...]
1222 capture_sequence:
1223 {(&) | (=)} [(capture) (capture) ...]
1224 capture:
1225 [&]variable | this_
1226 @endcode
1227 On compilers that do not support variadic macros\, <c>capture_tuple</c> cannot
1228 be used:
1229 @code
1230 capture_list:
1231 void | capture_sequence
1232 @endcode
1233 Furthermore\, on C++11 compilers that support the use of <c>typename</c>
1234 outside templates\, also <c>this</c> can be used to capture the object at member
1235 function scope:
1236 @code
1237 capture:
1238 [&]variable | this_ | this
1239 @endcode
1240
1241 (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or
1242 <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing;
1243 <c>{expression}</c> means the token resulting from the expression.)
1244 }
1245 @EndParams
1246
1247 Note that on compilers with variadic macro support (which should be all C++11
1248 compilers), the capture list can be specified as a comma-separated list.
1249 On all compilers, the same macro @RefMacro{BOOST_SCOPE_EXIT_ALL} also allows to
1250 specify the capture list as a Boost.Preprocessor sequence.
1251
1252 The capture list must always contain at least the leading <c>&</c> or <c>=</c>
1253 so it can never be <c>void</c> (<c>BOOST_SCOPE_EXIT(void)</c> should be used
1254 to program scope exits with an empty capture list).
1255
1256 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_ALL_ID} must be used
1257 instead of @RefMacro{BOOST_SCOPE_EXIT_ALL} when it is necessary to expand
1258 multiple scope exit declarations on the same line.
1259
1260 @Warning This macro capture list follows the exact same syntax of C++11 lambda
1261 captures which is unfortunately different from the syntax of
1262 @RefMacro{BOOST_SCOPE_EXIT} captures (unless programmers define the
1263 @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS} macro).
1264 For example, like C++11 lambda functions, @RefMacro{BOOST_SCOPE_EXIT_ALL}
1265 requires to capture data members by capturing the object <c>this</c> while
1266 @RefMacro{BOOST_SCOPE_EXIT} allows to capture data members directly and without
1267 capturing the object.
1268
1269 @Warning The implementation executes the scope exit body within a destructor
1270 thus the scope exit body must never throw in order to comply with STL exception
1271 safety requirements.
1272
1273 @Note This macro can always be used also within templates (so there is no need
1274 for a <c>BOOST_SCOPE_EXIT_ALL_TPL</c> macro).
1275
1276 @See @RefSect{tutorial, Tutorial} section,
1277 @RefSect{no_variadic_macros, No Variadic Macros} section,
1278 @RefMacro{BOOST_SCOPE_EXIT}, @RefMacro{BOOST_SCOPE_EXIT_ALL_ID}.
1279 */
1280 #define BOOST_SCOPE_EXIT_ALL(capture_list)
1281
1282 /**
1283 @brief This macro allows to expand on the same line multiple scope exits that
1284 capture all variables in scope (C++11 only).
1285
1286 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_ALL} but it can be
1287 expanded multiple times on the same line if different identifiers <c>id</c> are
1288 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_ALL} for more
1289 information).
1290 As with @RefMacro{BOOST_SCOPE_EXIT_ALL}, this macro is only available on C++11
1291 compilers (specifically, on C++11 compilers that do not define the
1292 Boost.Config <c>BOOST_NO_CXX11_LAMBDAS</c> macro).
1293
1294 @Params
1295 @Param{id,
1296 A unique identifier token which can be concatenated by the preprocessor
1297 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1298 alphanumeric tokens\, etc).
1299 }
1300 @Param{capture_list,
1301 Same as the <c>capture_list</c> parameter of the
1302 @RefMacro{BOOST_SCOPE_EXIT_ALL} macro.
1303 }
1304 @EndParams
1305
1306 @Note This macro can be useful when the scope exit macros are expanded
1307 within user-defined macros (because nested macros expand on the same line).
1308 On some compilers (e.g., MSVC which supports the non standard
1309 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1310 the use of this macro is always necessary to ensure portability when expanding
1311 multiple scope exit declarations on the same line.
1312
1313 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT_ALL},
1314 @RefMacro{BOOST_SCOPE_EXIT_ID}.
1315 */
1316 #define BOOST_SCOPE_EXIT_ALL_ID(id, capture_list)
1317
1318 /**
1319 @brief This macro marks the end of a scope exit body.
1320
1321 This macro must follow the closing curly bracket <c>}</c> that ends the body of
1322 either @RefMacro{BOOST_SCOPE_EXIT} or @RefMacro{BOOST_SCOPE_EXIT_TPL}:
1323
1324 @code
1325 { // Some local scope.
1326 ...
1327 BOOST_SCOPE_EXIT(capture_list) {
1328 ... // Body code.
1329 } BOOST_SCOPE_EXIT_END
1330 ...
1331 }
1332 @endcode
1333
1334 In general, the special macro @RefMacro{BOOST_SCOPE_EXIT_END_ID} must be used
1335 instead of @RefMacro{BOOST_SCOPE_EXIT_END} when it is necessary to expand
1336 multiple scope exit bodies on the same line.
1337
1338 @Note If programmers define the @RefMacro{BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS}
1339 macro on C++11 compilers, a semicolon <c>;</c> can be used instead of this
1340 macro.
1341 However, to maximize portability, it is recommended to always use
1342 @RefMacro{BOOST_SCOPE_EXIT_END}.
1343
1344 @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_SCOPE_EXIT},
1345 @RefMacro{BOOST_SCOPE_EXIT_TPL}, @RefMacro{BOOST_SCOPE_EXIT_END_ID}.
1346 */
1347 #define BOOST_SCOPE_EXIT_END
1348
1349 /**
1350 @brief This macro allows to terminate multiple scope exit bodies on the same
1351 line.
1352
1353 This macro is equivalent to @RefMacro{BOOST_SCOPE_EXIT_END} but it can be
1354 expanded multiple times on the same line if different identifiers <c>id</c> are
1355 provided for each expansion (see @RefMacro{BOOST_SCOPE_EXIT_END} for more
1356 information).
1357
1358 @Params
1359 @Param{id,
1360 A unique identifier token which can be concatenated by the preprocessor
1361 (<c>__LINE__</c>\, <c>scope_exit_number_1_on_line_123</c>\, a combination of
1362 alphanumeric tokens\, etc).
1363 }
1364 @EndParams
1365
1366 @Note This macro can be useful when the scope exit macros are expanded
1367 within user-defined macros (because macros all expand on the same line).
1368 On some compilers (e.g., MSVC which supports the non standard
1369 <c>__COUNTER__</c> macro) it might not be necessary to use this macro but
1370 the use of this macro is always necessary to ensure portability when expanding
1371 multiple scope exit macros on the same line (because this library can only
1372 portably use <c>__LINE__</c> to internally generate unique identifiers).
1373
1374 @See @RefMacro{BOOST_SCOPE_EXIT_ID}, @RefMacro{BOOST_SCOPE_EXIT_ID_TPL},
1375 @RefMacro{BOOST_SCOPE_EXIT_END}.
1376 */
1377 #define BOOST_SCOPE_EXIT_END_ID(id)
1378
1379 /**
1380 @brief Force to use C++11 lambda functions to implement scope exits.
1381
1382 If programmers define this configuration macro on a C++11 compiler for which
1383 the Boost.Config macro <c>BOOST_NO_CXX11_LAMBDAS</c> is not defined, the
1384 @RefMacro{BOOST_SCOPE_EXIT} and @RefMacro{BOOST_SCOPE_EXIT_TPL} macros will use
1385 C++11 lambda functions to declare scope exits.
1386 By default this macro is not defined.
1387
1388 @Warning When scope exits are implemented using lambda functions, the syntax of
1389 the capture list follows the exact same syntax of C++11 lambda captures
1390 which is in general different from the legacy capture syntax of this library.
1391 For example, C++11 lambdas require to capture data members by capturing the
1392 object <c>this</c> while this library always allowed to capture data members
1393 directly.
1394 Therefore, when this configuration macro is defined,
1395 @RefMacro{BOOST_SCOPE_EXIT} and @RefMacro{BOOST_SCOPE_EXIT_TPL} are no longer
1396 backward compatible (and this is why this macro is not defined by default).
1397
1398 A semicolon <c>;</c> can be used instead of @RefMacro{BOOST_SCOPE_EXIT_END}
1399 when this configuration macro is defined (but it is recommended to always use
1400 @RefMacro{BOOST_SCOPE_EXIT_END} so to maximize portability).
1401
1402 @Note This configuration macro does not control the definition of
1403 @RefMacro{BOOST_SCOPE_EXIT_ALL} which is always and automatically defined on
1404 compilers that support C++11 lambda functions.
1405
1406 @See @RefMacro{BOOST_SCOPE_EXIT}, @RefMacro{BOOST_SCOPE_EXIT_TPL},
1407 @RefMacro{BOOST_SCOPE_EXIT_END}.
1408 */
1409 #define BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS
1410
1411 #endif // DOXYGEN
1412
1413 #endif // BOOST_SCOPE_EXIT_HPP
1414
1415