File indexing completed on 2025-09-16 08:37:42
0001 #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
0002 #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/leaf/config.hpp>
0009 #include <boost/leaf/context.hpp>
0010 #include <typeinfo>
0011
0012 namespace boost { namespace leaf {
0013
0014 template <class T>
0015 class BOOST_LEAF_SYMBOL_VISIBLE result;
0016
0017
0018
0019 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0020
0021 namespace detail
0022 {
0023 inline error_id unpack_error_id(std::exception const & ex) noexcept
0024 {
0025 if( detail::exception_base const * eb = dynamic_cast<detail::exception_base const *>(&ex) )
0026 return eb->get_error_id();
0027 if( error_id const * err_id = dynamic_cast<error_id const *>(&ex) )
0028 return *err_id;
0029 return current_error();
0030 }
0031 }
0032
0033 #endif
0034
0035
0036
0037 class BOOST_LEAF_SYMBOL_VISIBLE error_info
0038 {
0039 error_info & operator=( error_info const & ) = delete;
0040
0041 error_id const err_id_;
0042 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0043 std::exception * const ex_;
0044 #endif
0045 e_source_location const * const loc_;
0046
0047 protected:
0048
0049 error_info( error_info const & ) noexcept = default;
0050
0051 public:
0052
0053 BOOST_LEAF_CONSTEXPR error_info(error_id id, std::exception * ex, e_source_location const * loc) noexcept:
0054 err_id_(id),
0055 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0056 ex_(ex),
0057 #endif
0058 loc_(loc)
0059 {
0060 (void) ex;
0061 }
0062
0063 BOOST_LEAF_CONSTEXPR error_id error() const noexcept
0064 {
0065 return err_id_;
0066 }
0067
0068 BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
0069 {
0070 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0071 return nullptr;
0072 #else
0073 return ex_;
0074 #endif
0075 }
0076
0077 BOOST_LEAF_CONSTEXPR e_source_location const * source_location() const noexcept
0078 {
0079 return loc_;
0080 }
0081
0082 template <class CharT, class Traits>
0083 void print_error_info(std::basic_ostream<CharT, Traits> & os) const
0084 {
0085 os << "Error with serial #" << err_id_;
0086 if( loc_ )
0087 os << " reported at " << *loc_;
0088 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0089 if( ex_ )
0090 {
0091 os << "\nCaught:" BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER;
0092 #if BOOST_LEAF_CFG_DIAGNOSTICS
0093 if( auto eb = dynamic_cast<detail::exception_base const *>(ex_) )
0094 eb->print_type_name(os);
0095 else
0096 #endif
0097 detail::demangle_and_print(os, typeid(*ex_).name());
0098 os << ": \"" << ex_->what() << '"';
0099 }
0100 #endif
0101 }
0102
0103 template <class CharT, class Traits>
0104 friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, error_info const & x)
0105 {
0106 x.print_error_info(os);
0107 return os << '\n';
0108 }
0109 };
0110
0111 namespace detail
0112 {
0113 template <>
0114 struct handler_argument_traits<error_info const &>: handler_argument_always_available<>
0115 {
0116 template <class Tup>
0117 BOOST_LEAF_CONSTEXPR static error_info const & get(Tup const &, error_info const & ei) noexcept
0118 {
0119 return ei;
0120 }
0121 };
0122 }
0123
0124
0125
0126 namespace detail
0127 {
0128 template <class T, class... List>
0129 struct type_index;
0130
0131 template <class T, class... Cdr>
0132 struct type_index<T, T, Cdr...>
0133 {
0134 constexpr static int value = 0;
0135 };
0136
0137 template <class T, class Car, class... Cdr>
0138 struct type_index<T, Car, Cdr...>
0139 {
0140 constexpr static int value = 1 + type_index<T,Cdr...>::value;
0141 };
0142
0143 template <class T, class Tup>
0144 struct tuple_type_index;
0145
0146 template <class T, class... TupleTypes>
0147 struct tuple_type_index<T,std::tuple<TupleTypes...>>
0148 {
0149 constexpr static int value = type_index<T,TupleTypes...>::value;
0150 };
0151
0152 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0153
0154 template <class E, bool = std::is_class<E>::value>
0155 struct peek_exception;
0156
0157 template <>
0158 struct peek_exception<std::exception const, true>
0159 {
0160 BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
0161 {
0162 return ei.exception();
0163 }
0164 };
0165
0166 template <>
0167 struct peek_exception<std::exception, true>
0168 {
0169 BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
0170 {
0171 return ei.exception();
0172 }
0173 };
0174
0175 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0176 template <>
0177 struct peek_exception<std::error_code const, true>
0178 {
0179 static std::error_code const * peek( error_info const & ei ) noexcept
0180 {
0181 auto const ex = ei.exception();
0182 if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
0183 return &se->code();
0184 else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
0185 return ec;
0186 else
0187 return nullptr;
0188 }
0189 };
0190
0191 template <>
0192 struct peek_exception<std::error_code, true>
0193 {
0194 static std::error_code * peek( error_info const & ei ) noexcept
0195 {
0196 auto const ex = ei.exception();
0197 if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
0198 return const_cast<std::error_code *>(&se->code());
0199 else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
0200 return ec;
0201 else
0202 return nullptr;
0203 }
0204 };
0205 #endif
0206
0207 template <class E>
0208 struct peek_exception<E, true>
0209 {
0210 static E * peek( error_info const & ei ) noexcept
0211 {
0212 return dynamic_cast<E *>(ei.exception());
0213 }
0214 };
0215
0216 template <class E>
0217 struct peek_exception<E, false>
0218 {
0219 BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
0220 {
0221 return nullptr;
0222 }
0223 };
0224
0225 #endif
0226
0227 template <class E, bool = does_not_participate_in_context_deduction<E>::value>
0228 struct peek_tuple;
0229
0230 template <class E>
0231 struct peek_tuple<E, true>
0232 {
0233 template <class SlotsTuple>
0234 BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const &, error_id const & ) noexcept
0235 {
0236 return nullptr;
0237 }
0238
0239 template <class SlotsTuple>
0240 BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple &, error_id const & ) noexcept
0241 {
0242 return nullptr;
0243 }
0244 };
0245
0246 template <class E>
0247 struct peek_tuple<E, false>
0248 {
0249 template <class SlotsTuple>
0250 BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const & tup, error_id const & err ) noexcept
0251 {
0252 return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
0253 }
0254
0255 template <class SlotsTuple>
0256 BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple & tup, error_id const & err ) noexcept
0257 {
0258 return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
0259 }
0260 };
0261
0262 template <class E, class SlotsTuple>
0263 BOOST_LEAF_CONSTEXPR inline
0264 E const *
0265 peek( SlotsTuple const & tup, error_info const & ei ) noexcept
0266 {
0267 if( error_id err = ei.error() )
0268 {
0269 if( E const * e = peek_tuple<E>::peek(tup, err) )
0270 return e;
0271 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0272 else
0273 return peek_exception<E const>::peek(ei);
0274 #endif
0275 }
0276 return nullptr;
0277 }
0278
0279 template <class E, class SlotsTuple>
0280 BOOST_LEAF_CONSTEXPR inline
0281 E *
0282 peek( SlotsTuple & tup, error_info const & ei ) noexcept
0283 {
0284 if( error_id err = ei.error() )
0285 {
0286 if( E * e = peek_tuple<E>::peek(tup, err) )
0287 return e;
0288 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0289 else
0290 return peek_exception<E>::peek(ei);
0291 #endif
0292 }
0293 return nullptr;
0294 }
0295 }
0296
0297
0298
0299 namespace detail
0300 {
0301 template <class A>
0302 template <class Tup>
0303 BOOST_LEAF_CONSTEXPR inline
0304 typename handler_argument_traits_defaults<A, false>::error_type const *
0305 handler_argument_traits_defaults<A, false>::
0306 check( Tup const & tup, error_info const & ei ) noexcept
0307 {
0308 return peek<typename std::decay<A>::type>(tup, ei);
0309 }
0310
0311 template <class A>
0312 template <class Tup>
0313 BOOST_LEAF_CONSTEXPR inline
0314 typename handler_argument_traits_defaults<A, false>::error_type *
0315 handler_argument_traits_defaults<A, false>::
0316 check( Tup & tup, error_info const & ei ) noexcept
0317 {
0318 return peek<typename std::decay<A>::type>(tup, ei);
0319 }
0320
0321 template <class Tup>
0322 BOOST_LEAF_CONSTEXPR inline
0323 std::exception const *
0324 handler_argument_traits<void>::
0325 check( Tup const &, error_info const & ei ) noexcept
0326 {
0327 return ei.exception();
0328 }
0329
0330 template <class Tup, class... List>
0331 struct check_arguments;
0332
0333 template <class Tup>
0334 struct check_arguments<Tup>
0335 {
0336 BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
0337 {
0338 return true;
0339 }
0340 };
0341
0342 template <class Tup, class Car, class... Cdr>
0343 struct check_arguments<Tup, Car, Cdr...>
0344 {
0345 BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
0346 {
0347 return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
0348 }
0349 };
0350 }
0351
0352
0353
0354 namespace detail
0355 {
0356 template <class>
0357 struct handler_matches_any_error: std::false_type
0358 {
0359 };
0360
0361 template <template<class...> class L>
0362 struct handler_matches_any_error<L<>>: std::true_type
0363 {
0364 };
0365
0366 template <template<class...> class L, class Car, class... Cdr>
0367 struct handler_matches_any_error<L<Car, Cdr...>>
0368 {
0369 constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
0370 };
0371 }
0372
0373
0374
0375 namespace detail
0376 {
0377 template <class Tup, class... A>
0378 BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
0379 {
0380 return check_arguments<Tup, A...>::check(tup, ei);
0381 }
0382
0383 template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
0384 struct handler_caller
0385 {
0386 template <class Tup, class... A>
0387 BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
0388 {
0389 return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
0390 }
0391 };
0392
0393 template <template <class...> class Result, class... E, class F>
0394 struct handler_caller<Result<void, E...>, F, true, void>
0395 {
0396 using R = Result<void, E...>;
0397
0398 template <class Tup, class... A>
0399 BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
0400 {
0401 std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
0402 return { };
0403 }
0404 };
0405
0406 template <class T>
0407 struct is_tuple: std::false_type { };
0408
0409 template <class... T>
0410 struct is_tuple<std::tuple<T...>>: std::true_type { };
0411
0412 template <class... T>
0413 struct is_tuple<std::tuple<T...> &>: std::true_type { };
0414
0415 template <class R, class Tup, class H>
0416 BOOST_LEAF_CONSTEXPR inline
0417 typename std::enable_if<!is_tuple<typename std::decay<H>::type>::value, R>::type
0418 handle_error_( Tup & tup, error_info const & ei, H && h )
0419 {
0420 static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
0421 return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
0422 }
0423
0424 template <class R, class Tup, class Car, class... Cdr>
0425 BOOST_LEAF_CONSTEXPR inline
0426 typename std::enable_if<!is_tuple<typename std::decay<Car>::type>::value, R>::type
0427 handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
0428 {
0429 if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
0430 return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
0431 else
0432 return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
0433 }
0434
0435 template <class R, class Tup, class HTup, size_t ... I>
0436 BOOST_LEAF_CONSTEXPR inline
0437 R
0438 handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
0439 {
0440 return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
0441 }
0442
0443 template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
0444 BOOST_LEAF_CONSTEXPR inline
0445 R
0446 handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
0447 {
0448 return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
0449 }
0450
0451 template <class R, class Tup, class H>
0452 BOOST_LEAF_CONSTEXPR inline
0453 typename std::enable_if<is_tuple<typename std::decay<H>::type>::value, R>::type
0454 handle_error_( Tup & tup, error_info const & ei, H && h )
0455 {
0456 return handle_error_tuple_<R>(
0457 tup,
0458 ei,
0459 leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
0460 std::forward<H>(h));
0461 }
0462
0463 template <class R, class Tup, class Car, class... Cdr>
0464 BOOST_LEAF_CONSTEXPR inline
0465 typename std::enable_if<is_tuple<typename std::decay<Car>::type>::value, R>::type
0466 handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
0467 {
0468 return handle_error_tuple_<R>(
0469 tup,
0470 ei,
0471 leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
0472 std::forward<Car>(car),
0473 std::forward<Cdr>(cdr)...);
0474 }
0475 }
0476
0477
0478
0479 template <class... E>
0480 template <class R, class... H>
0481 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
0482 R
0483 context<E...>::
0484 handle_error( error_id id, H && ... h ) const
0485 {
0486 BOOST_LEAF_ASSERT(!is_active());
0487 return detail::handle_error_<R>(tup(), error_info(id, nullptr, this->get<e_source_location>(id)), std::forward<H>(h)...);
0488 }
0489
0490 template <class... E>
0491 template <class R, class... H>
0492 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
0493 R
0494 context<E...>::
0495 handle_error( error_id id, H && ... h )
0496 {
0497 BOOST_LEAF_ASSERT(!is_active());
0498 return detail::handle_error_<R>(tup(), error_info(id, nullptr, this->get<e_source_location>(id)), std::forward<H>(h)...);
0499 }
0500
0501
0502
0503 namespace detail
0504 {
0505 template <class T>
0506 void unload_result( result<T> * r )
0507 {
0508 (void) r->unload();
0509 }
0510
0511 inline void unload_result( void * )
0512 {
0513 }
0514 }
0515
0516
0517
0518 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0519
0520 template <class TryBlock, class... H>
0521 BOOST_LEAF_CONSTEXPR inline
0522 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
0523 try_handle_all( TryBlock && try_block, H && ... h ) noexcept
0524 {
0525 static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
0526 context_type_from_handlers<H...> ctx;
0527 auto active_context = activate_context(ctx);
0528 if( auto r = std::forward<TryBlock>(try_block)() )
0529 return std::move(r).value();
0530 else
0531 {
0532 detail::unload_result(&r);
0533 error_id id(r.error());
0534 ctx.deactivate();
0535 using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
0536 return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
0537 }
0538 }
0539
0540 template <class TryBlock, class... H>
0541 BOOST_LEAF_ATTRIBUTE_NODISCARD BOOST_LEAF_CONSTEXPR inline
0542 typename std::decay<decltype(std::declval<TryBlock>()())>::type
0543 try_handle_some( TryBlock && try_block, H && ... h ) noexcept
0544 {
0545 static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
0546 context_type_from_handlers<H...> ctx;
0547 auto active_context = activate_context(ctx);
0548 if( auto r = std::forward<TryBlock>(try_block)() )
0549 return r;
0550 else
0551 {
0552 detail::unload_result(&r);
0553 error_id id(r.error());
0554 ctx.deactivate();
0555 using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
0556 auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
0557 if( !rr )
0558 ctx.unload(error_id(rr.error()));
0559 return rr;
0560 }
0561 }
0562
0563 template <class TryBlock, class... H>
0564 BOOST_LEAF_CONSTEXPR inline
0565 decltype(std::declval<TryBlock>()())
0566 try_catch( TryBlock && try_block, H && ... ) noexcept
0567 {
0568 static_assert(sizeof(context_type_from_handlers<H...>) > 0,
0569 "When exceptions are disabled, try_catch can't fail and has no use for the handlers, but this ensures that the supplied H... types are compatible.");
0570 return std::forward<TryBlock>(try_block)();
0571 }
0572
0573 #else
0574
0575 namespace detail
0576 {
0577 template <class Ctx, class TryBlock, class... H>
0578 decltype(std::declval<TryBlock>()())
0579 try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
0580 {
0581 using namespace detail;
0582 BOOST_LEAF_ASSERT(ctx.is_active());
0583 using R = decltype(std::declval<TryBlock>()());
0584 try
0585 {
0586 auto r = std::forward<TryBlock>(try_block)();
0587 unload_result(&r);
0588 return r;
0589 }
0590 catch( std::exception & ex )
0591 {
0592 ctx.deactivate();
0593 error_id id = detail::unpack_error_id(ex);
0594 return handle_error_<R>(ctx.tup(), error_info(id, &ex, ctx.template get<e_source_location>(id)), std::forward<H>(h)...,
0595 [&]() -> R
0596 {
0597 ctx.unload(id);
0598 throw;
0599 } );
0600 }
0601 catch(...)
0602 {
0603 ctx.deactivate();
0604 error_id id = current_error();
0605 return handle_error_<R>(ctx.tup(), error_info(id, nullptr, ctx.template get<e_source_location>(id)), std::forward<H>(h)...,
0606 [&]() -> R
0607 {
0608 ctx.unload(id);
0609 throw;
0610 } );
0611 }
0612 }
0613 }
0614
0615 template <class TryBlock, class... H>
0616 inline
0617 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
0618 try_handle_all( TryBlock && try_block, H && ... h )
0619 {
0620 static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to try_handle_all must be registered with leaf::is_result_type");
0621 context_type_from_handlers<H...> ctx;
0622 auto active_context = activate_context(ctx);
0623 if( auto r = detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
0624 return std::move(r).value();
0625 else
0626 {
0627 BOOST_LEAF_ASSERT(ctx.is_active());
0628 detail::unload_result(&r);
0629 error_id id(r.error());
0630 ctx.deactivate();
0631 using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
0632 return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
0633 }
0634 }
0635
0636 template <class TryBlock, class... H>
0637 BOOST_LEAF_ATTRIBUTE_NODISCARD inline
0638 typename std::decay<decltype(std::declval<TryBlock>()())>::type
0639 try_handle_some( TryBlock && try_block, H && ... h )
0640 {
0641 static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to try_handle_some must be registered with leaf::is_result_type");
0642 context_type_from_handlers<H...> ctx;
0643 auto active_context = activate_context(ctx);
0644 if( auto r = detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
0645 return r;
0646 else if( ctx.is_active() )
0647 {
0648 detail::unload_result(&r);
0649 error_id id(r.error());
0650 ctx.deactivate();
0651 using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
0652 auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...,
0653 [&r]()->R
0654 {
0655 return std::move(r);
0656 });
0657 if( !rr )
0658 ctx.unload(error_id(rr.error()));
0659 return rr;
0660 }
0661 else
0662 {
0663 ctx.unload(error_id(r.error()));
0664 return r;
0665 }
0666 }
0667
0668 template <class TryBlock, class... H>
0669 inline
0670 decltype(std::declval<TryBlock>()())
0671 try_catch( TryBlock && try_block, H && ... h )
0672 {
0673 context_type_from_handlers<H...> ctx;
0674 auto active_context = activate_context(ctx);
0675 using R = decltype(std::declval<TryBlock>()());
0676 try
0677 {
0678 return std::forward<TryBlock>(try_block)();
0679 }
0680 catch( std::exception & ex )
0681 {
0682 ctx.deactivate();
0683 error_id id = detail::unpack_error_id(ex);
0684 return detail::handle_error_<R>(ctx.tup(), error_info(id, &ex, ctx.template get<e_source_location>(id)), std::forward<H>(h)...,
0685 [&]() -> R
0686 {
0687 ctx.unload(id);
0688 throw;
0689 } );
0690 }
0691 catch(...)
0692 {
0693 ctx.deactivate();
0694 error_id id = current_error();
0695 return detail::handle_error_<R>(ctx.tup(), error_info(id, nullptr, ctx.template get<e_source_location>(id)), std::forward<H>(h)...,
0696 [&]() -> R
0697 {
0698 ctx.unload(id);
0699 throw;
0700 } );
0701 }
0702 }
0703
0704 #endif
0705
0706 #if BOOST_LEAF_CFG_CAPTURE
0707
0708 namespace detail
0709 {
0710 template <class LeafResult>
0711 struct try_capture_all_dispatch_non_void
0712 {
0713 using leaf_result = LeafResult;
0714
0715 template <class TryBlock>
0716 inline
0717 static
0718 leaf_result
0719 try_capture_all_( TryBlock && try_block ) noexcept
0720 {
0721 detail::slot<detail::dynamic_allocator> sl;
0722 sl.activate();
0723 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0724 try
0725 #endif
0726 {
0727 if( leaf_result r = std::forward<TryBlock>(try_block)() )
0728 {
0729 sl.deactivate();
0730 return r;
0731 }
0732 else
0733 {
0734 sl.deactivate();
0735 int const err_id = error_id(r.error()).value();
0736 return leaf_result(sl.value_or_default(err_id).template extract_capture_list<leaf_result>(err_id));
0737 }
0738 }
0739 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0740 catch( std::exception & ex )
0741 {
0742 sl.deactivate();
0743 int err_id = unpack_error_id(ex).value();
0744 return sl.value_or_default(err_id).template extract_capture_list<leaf_result>(err_id);
0745 }
0746 catch(...)
0747 {
0748 sl.deactivate();
0749 int err_id = current_error().value();
0750 return sl.value_or_default(err_id).template extract_capture_list<leaf_result>(err_id);
0751 }
0752 #endif
0753 }
0754 };
0755
0756 template <class R, bool IsVoid = std::is_same<void, R>::value, bool IsResultType = is_result_type<R>::value>
0757 struct try_capture_all_dispatch;
0758
0759 template <class R>
0760 struct try_capture_all_dispatch<R, false, true>:
0761 try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::decay<decltype(std::declval<R>().value())>::type>>
0762 {
0763 };
0764
0765 template <class R>
0766 struct try_capture_all_dispatch<R, false, false>:
0767 try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::remove_reference<R>::type>>
0768 {
0769 };
0770
0771 template <class R>
0772 struct try_capture_all_dispatch<R, true, false>
0773 {
0774 using leaf_result = ::boost::leaf::result<R>;
0775
0776 template <class TryBlock>
0777 inline
0778 static
0779 leaf_result
0780 try_capture_all_( TryBlock && try_block ) noexcept
0781 {
0782 detail::slot<detail::dynamic_allocator> sl;
0783 sl.activate();
0784 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0785 try
0786 #endif
0787 {
0788 std::forward<TryBlock>(try_block)();
0789 return {};
0790 }
0791 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0792 catch( std::exception & ex )
0793 {
0794 sl.deactivate();
0795 int err_id = unpack_error_id(ex).value();
0796 return sl.value_or_default(err_id).template extract_capture_list<leaf_result>(err_id);
0797 }
0798 catch(...)
0799 {
0800 sl.deactivate();
0801 int err_id = current_error().value();
0802 return sl.value_or_default(err_id).template extract_capture_list<leaf_result>(err_id);
0803 }
0804 #endif
0805 }
0806 };
0807 }
0808
0809 template <class TryBlock>
0810 inline
0811 typename detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::leaf_result
0812 try_capture_all( TryBlock && try_block ) noexcept
0813 {
0814 return detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::try_capture_all_(std::forward<TryBlock>(try_block));
0815 }
0816 #endif
0817
0818 } }
0819
0820
0821
0822 namespace boost { class exception; }
0823 namespace boost { template <class Tag,class T> class error_info; }
0824 namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
0825
0826 namespace boost { namespace leaf {
0827
0828 namespace detail
0829 {
0830 template <class T>
0831 struct match_enum_type;
0832
0833 template <class Tag, class T>
0834 struct match_enum_type<boost::error_info<Tag, T>>
0835 {
0836 using type = T;
0837 };
0838
0839 template <class Ex>
0840 BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
0841 {
0842 return dynamic_cast<Ex *>(ei.exception());
0843 }
0844
0845 template <class, class T>
0846 struct dependent_type { using type = T; };
0847
0848 template <class Dep, class T>
0849 using dependent_type_t = typename dependent_type<Dep, T>::type;
0850
0851 template <class Tag, class T>
0852 struct handler_argument_traits<boost::error_info<Tag, T>>
0853 {
0854 using context_types = leaf_detail_mp11::mp_list<>;
0855 constexpr static bool always_available = false;
0856
0857 template <class Tup>
0858 BOOST_LEAF_CONSTEXPR static T * check( Tup &, error_info const & ei ) noexcept
0859 {
0860 using boost_exception = dependent_type_t<T, boost::exception>;
0861 if( auto * be = get_exception<boost_exception>(ei) )
0862 return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
0863 else
0864 return nullptr;
0865 }
0866
0867 template <class Tup>
0868 BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
0869 {
0870 return boost::error_info<Tag, T>(*check(tup, ei));
0871 }
0872 };
0873
0874 template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
0875 template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> const *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
0876 template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> &>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
0877 template <class Tag, class T> struct handler_argument_traits<boost::error_info<Tag, T> *>: handler_argument_traits_require_by_value<boost::error_info<Tag, T>> { };
0878 }
0879
0880 } }
0881
0882 #endif