the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1316 lines 50 kB view raw
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