Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // Boost Exception Integration
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 // BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED