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