Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-09 08:14:21

0001 #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
0002 #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
0003 
0004 // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
0005 
0006 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0007 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #include <boost/leaf/config.hpp>
0010 #include <boost/leaf/context.hpp>
0011 
0012 namespace boost { namespace leaf {
0013 
0014 template <class T>
0015 class BOOST_LEAF_SYMBOL_VISIBLE result;
0016 
0017 ////////////////////////////////////////
0018 
0019 class BOOST_LEAF_SYMBOL_VISIBLE error_info
0020 {
0021     error_info & operator=( error_info const & ) = delete;
0022 
0023 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0024     static error_id unpack_error_id( std::exception const * ex ) noexcept
0025     {
0026         if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
0027             return *err_id;
0028         return current_error();
0029     }
0030 
0031     std::exception * const ex_;
0032 #endif
0033 
0034     error_id const err_id_;
0035 
0036 protected:
0037 
0038     error_info( error_info const & ) noexcept = default;
0039 
0040 public:
0041 
0042     BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
0043 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0044         ex_(nullptr),
0045 #endif
0046         err_id_(id)
0047     {
0048     }
0049 
0050 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0051     explicit error_info( std::exception * ex ) noexcept:
0052         ex_(ex),
0053         err_id_(unpack_error_id(ex_))
0054     {
0055     }
0056 #endif
0057 
0058     BOOST_LEAF_CONSTEXPR error_id error() const noexcept
0059     {
0060         return err_id_;
0061     }
0062 
0063     BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
0064     {
0065 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0066         return nullptr;
0067 #else
0068         return ex_;
0069 #endif
0070     }
0071 
0072     template <class CharT, class Traits>
0073     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, error_info const & x )
0074     {
0075         os << "Error ID: " << x.err_id_.value();
0076 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0077         if( x.ex_ )
0078         {
0079             os <<
0080                 "\nException dynamic type: " << leaf_detail::demangle(typeid(*x.ex_).name()) <<
0081                 "\nstd::exception::what(): " << x.ex_->what();
0082         }
0083 #endif
0084         return os << '\n';
0085     }
0086 };
0087 
0088 namespace leaf_detail
0089 {
0090     template <>
0091     struct handler_argument_traits<error_info const &>: handler_argument_always_available<void>
0092     {
0093         template <class Tup>
0094         BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept
0095         {
0096             return ei;
0097         }
0098     };
0099 }
0100 
0101 ////////////////////////////////////////
0102 
0103 #if BOOST_LEAF_CFG_DIAGNOSTICS
0104 
0105 class diagnostic_info: public error_info
0106 {
0107     void const * tup_;
0108     void (*print_context_content_)( std::ostream &, void const * tup, int err_id_to_print );
0109 
0110 protected:
0111 
0112     diagnostic_info( diagnostic_info const & ) noexcept = default;
0113 
0114     template <class Tup>
0115     BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
0116         error_info(ei),
0117         tup_(&tup),
0118         print_context_content_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
0119     {
0120     }
0121 
0122     template <class CharT, class Traits>
0123     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
0124     {
0125         os << static_cast<error_info const &>(x);
0126         x.print_context_content_(os, x.tup_, x.error().value());
0127         return os;
0128     }
0129 };
0130 
0131 namespace leaf_detail
0132 {
0133     struct diagnostic_info_: diagnostic_info
0134     {
0135         template <class Tup>
0136         BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, Tup const & tup ) noexcept:
0137             diagnostic_info(ei, tup)
0138         {
0139         }
0140     };
0141 
0142     template <>
0143     struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
0144     {
0145         template <class Tup>
0146         BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
0147         {
0148             return diagnostic_info_(ei, tup);
0149         }
0150     };
0151 }
0152 
0153 #else
0154 
0155 class diagnostic_info: public error_info
0156 {
0157 protected:
0158 
0159     diagnostic_info( diagnostic_info const & ) noexcept = default;
0160 
0161     BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
0162         error_info(ei)
0163     {
0164     }
0165 
0166     template <class CharT, class Traits>
0167     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
0168     {
0169         return os << "diagnostic_info not available due to BOOST_LEAF_CFG_DIAGNOSTICS=0. Basic error_info follows.\n" << static_cast<error_info const &>(x);
0170     }
0171 };
0172 
0173 namespace leaf_detail
0174 {
0175     struct diagnostic_info_: diagnostic_info
0176     {
0177         BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
0178             diagnostic_info(ei)
0179         {
0180         }
0181     };
0182 
0183     template <>
0184     struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
0185     {
0186         template <class Tup>
0187         BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const &, error_info const & ei ) noexcept
0188         {
0189             return diagnostic_info_(ei);
0190         }
0191     };
0192 }
0193 
0194 #endif
0195 
0196 ////////////////////////////////////////
0197 
0198 #if BOOST_LEAF_CFG_DIAGNOSTICS
0199 
0200 #if BOOST_LEAF_CFG_CAPTURE
0201 
0202 class verbose_diagnostic_info: public diagnostic_info
0203 {
0204     leaf_detail::dynamic_allocator const * const da_;
0205 
0206 protected:
0207 
0208     verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
0209 
0210     template <class Tup>
0211     BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, Tup const & tup, leaf_detail::dynamic_allocator const * da ) noexcept:
0212         diagnostic_info(ei, tup),
0213         da_(da)
0214     {
0215     }
0216 
0217     template <class CharT, class Traits>
0218     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
0219     {
0220         os << static_cast<diagnostic_info const &>(x);
0221         if( x.da_ )
0222             x.da_->print(os, "Unhandled error objects:\n", x.error().value());
0223         return os;
0224     }
0225 };
0226 
0227 namespace leaf_detail
0228 {
0229     template <class T>
0230     struct get_dispatch
0231     {
0232         static BOOST_LEAF_CONSTEXPR T const * get(T const * x) noexcept
0233         {
0234             return x;
0235         }
0236         static BOOST_LEAF_CONSTEXPR T const * get(void const *) noexcept
0237         {
0238             return nullptr;
0239         }
0240     };
0241 
0242     template <class T, int I = 0, class... Tp>
0243     BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I == sizeof...(Tp) - 1, T>::type const *
0244     find_in_tuple(std::tuple<Tp...> const & t) noexcept
0245     {
0246         return get_dispatch<T>::get(&std::get<I>(t));
0247     }
0248 
0249     template<class T, int I = 0, class... Tp>
0250     BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I < sizeof...(Tp) - 1, T>::type const *
0251     find_in_tuple(std::tuple<Tp...> const & t) noexcept
0252     {
0253         if( T const * x = get_dispatch<T>::get(&std::get<I>(t)) )
0254             return x;
0255         else
0256             return find_in_tuple<T, I+1, Tp...>(t);
0257     }
0258 
0259     struct verbose_diagnostic_info_: verbose_diagnostic_info
0260     {
0261         template <class Tup>
0262         BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, Tup const & tup, dynamic_allocator const * da ) noexcept:
0263             verbose_diagnostic_info(ei, tup, da)
0264         {
0265         }
0266     };
0267 
0268     template <>
0269     struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<dynamic_allocator>
0270     {
0271         template <class Tup>
0272         BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
0273         {
0274             slot<dynamic_allocator> const * da = find_in_tuple<slot<dynamic_allocator>>(tup);
0275             return verbose_diagnostic_info_(ei, tup, da ? da->has_value() : nullptr );
0276         }
0277     };
0278 }
0279 
0280 #else
0281 
0282 class verbose_diagnostic_info: public diagnostic_info
0283 {
0284 protected:
0285 
0286     verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
0287 
0288     template <class Tup>
0289     BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
0290         diagnostic_info(ei, tup)
0291     {
0292     }
0293 
0294     template <class CharT, class Traits>
0295     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
0296     {
0297         return os << "verbose_diagnostic_info not available due to BOOST_LEAF_CFG_CAPTURE=0. Basic diagnostic_info follows.\n" << static_cast<diagnostic_info const &>(x);
0298     }
0299 };
0300 
0301 namespace leaf_detail
0302 {
0303     struct verbose_diagnostic_info_: verbose_diagnostic_info
0304     {
0305         template <class Tup>
0306         BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, Tup const & tup ) noexcept:
0307             verbose_diagnostic_info(ei, tup)
0308         {
0309         }
0310     };
0311 
0312     template <>
0313     struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
0314     {
0315         template <class Tup>
0316         BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
0317         {
0318             return verbose_diagnostic_info_(ei, tup);
0319         }
0320     };
0321 }
0322 
0323 #endif
0324 
0325 #else
0326 
0327 class verbose_diagnostic_info: public diagnostic_info
0328 {
0329 protected:
0330 
0331     verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
0332 
0333     BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
0334         diagnostic_info(ei)
0335     {
0336     }
0337 
0338     template <class CharT, class Traits>
0339     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
0340     {
0341         return os << "verbose_diagnostic_info not available due to BOOST_LEAF_CFG_DIAGNOSTICS=0. Basic error_info follows.\n" << static_cast<error_info const &>(x);
0342     }
0343 };
0344 
0345 namespace leaf_detail
0346 {
0347     struct verbose_diagnostic_info_: verbose_diagnostic_info
0348     {
0349         BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
0350             verbose_diagnostic_info(ei)
0351         {
0352         }
0353     };
0354 
0355     template <>
0356     struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
0357     {
0358         template <class Tup>
0359         BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const &, error_info const & ei ) noexcept
0360         {
0361             return verbose_diagnostic_info_(ei);
0362         }
0363     };
0364 }
0365 
0366 #endif
0367 
0368 ////////////////////////////////////////
0369 
0370 namespace leaf_detail
0371 {
0372     template <class T, class... List>
0373     struct type_index;
0374 
0375     template <class T, class... Cdr>
0376     struct type_index<T, T, Cdr...>
0377     {
0378         constexpr static int value = 0;
0379     };
0380 
0381     template <class T, class Car, class... Cdr>
0382     struct type_index<T, Car, Cdr...>
0383     {
0384         constexpr static int value = 1 + type_index<T,Cdr...>::value;
0385     };
0386 
0387     template <class T, class Tuple>
0388     struct tuple_type_index;
0389 
0390     template <class T, class... TupleTypes>
0391     struct tuple_type_index<T,std::tuple<TupleTypes...>>
0392     {
0393         constexpr static int value = type_index<T,TupleTypes...>::value;
0394     };
0395 
0396 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0397 
0398     template <class E, bool = std::is_class<E>::value>
0399     struct peek_exception;
0400 
0401     template <>
0402     struct peek_exception<std::exception const, true>
0403     {
0404         BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
0405         {
0406             return ei.exception();
0407         }
0408     };
0409 
0410     template <>
0411     struct peek_exception<std::exception, true>
0412     {
0413         BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
0414         {
0415             return ei.exception();
0416         }
0417     };
0418 
0419 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0420     template <>
0421     struct peek_exception<std::error_code const, true>
0422     {
0423         static std::error_code const * peek( error_info const & ei ) noexcept
0424         {
0425             auto const ex = ei.exception();
0426             if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
0427                 return &se->code();
0428             else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
0429                 return ec;
0430             else
0431                 return nullptr;
0432         }
0433     };
0434 
0435     template <>
0436     struct peek_exception<std::error_code, true>
0437     {
0438         static std::error_code * peek( error_info const & ei ) noexcept
0439         {
0440             auto const ex = ei.exception();
0441             if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
0442                 return const_cast<std::error_code *>(&se->code());
0443             else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
0444                 return ec;
0445             else
0446                 return nullptr;
0447         }
0448     };
0449 #endif
0450 
0451     template <class E>
0452     struct peek_exception<E, true>
0453     {
0454         static E * peek( error_info const & ei ) noexcept
0455         {
0456             return dynamic_cast<E *>(ei.exception());
0457         }
0458     };
0459 
0460     template <class E>
0461     struct peek_exception<E, false>
0462     {
0463         BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
0464         {
0465             return nullptr;
0466         }
0467     };
0468 
0469 #endif
0470 
0471     template <class E, bool = does_not_participate_in_context_deduction<E>::value>
0472     struct peek_tuple;
0473 
0474     template <class E>
0475     struct peek_tuple<E, true>
0476     {
0477         template <class SlotsTuple>
0478         BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const &, error_id const & ) noexcept
0479         {
0480             return nullptr;
0481         }
0482         
0483         template <class SlotsTuple>
0484         BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple &, error_id const & ) noexcept
0485         {
0486             return nullptr;
0487         }
0488     };
0489 
0490     template <class E>
0491     struct peek_tuple<E, false>
0492     {
0493         template <class SlotsTuple>
0494         BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const & tup, error_id const & err ) noexcept
0495         {
0496             return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
0497         }
0498 
0499         template <class SlotsTuple>
0500         BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple & tup, error_id const & err ) noexcept
0501         {
0502             return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
0503         }
0504     };
0505 
0506     template <class E, class SlotsTuple>
0507     BOOST_LEAF_CONSTEXPR inline
0508     E const *
0509     peek( SlotsTuple const & tup, error_info const & ei ) noexcept
0510     {
0511         if( error_id err = ei.error() )
0512         {
0513             if( E const * e = peek_tuple<E>::peek(tup, err) )
0514                 return e;
0515 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0516             else
0517                 return peek_exception<E const>::peek(ei);
0518 #endif
0519         }
0520         return nullptr;
0521     }
0522 
0523     template <class E, class SlotsTuple>
0524     BOOST_LEAF_CONSTEXPR inline
0525     E *
0526     peek( SlotsTuple & tup, error_info const & ei ) noexcept
0527     {
0528         if( error_id err = ei.error() )
0529         {
0530             if( E * e = peek_tuple<E>::peek(tup, err) )
0531                 return e;
0532 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0533             else
0534                 return peek_exception<E>::peek(ei);
0535 #endif
0536         }
0537         return nullptr;
0538     }
0539 }
0540 
0541 ////////////////////////////////////////
0542 
0543 namespace leaf_detail
0544 {
0545     template <class A>
0546     template <class Tup>
0547     BOOST_LEAF_CONSTEXPR inline
0548     typename handler_argument_traits_defaults<A, false>::error_type const *
0549     handler_argument_traits_defaults<A, false>::
0550     check( Tup const & tup, error_info const & ei ) noexcept
0551     {
0552         return peek<typename std::decay<A>::type>(tup, ei);
0553     }
0554 
0555     template <class A>
0556     template <class Tup>
0557     BOOST_LEAF_CONSTEXPR inline
0558     typename handler_argument_traits_defaults<A, false>::error_type *
0559     handler_argument_traits_defaults<A, false>::
0560     check( Tup & tup, error_info const & ei ) noexcept
0561     {
0562         return peek<typename std::decay<A>::type>(tup, ei);
0563     }
0564 
0565     template <class Tup>
0566     BOOST_LEAF_CONSTEXPR inline
0567     std::exception const *
0568     handler_argument_traits<void>::
0569     check( Tup const &, error_info const & ei ) noexcept
0570     {
0571         return ei.exception();
0572     }
0573 
0574     template <class Tup, class... List>
0575     struct check_arguments;
0576 
0577     template <class Tup>
0578     struct check_arguments<Tup>
0579     {
0580         BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
0581         {
0582             return true;
0583         }
0584     };
0585 
0586     template <class Tup, class Car, class... Cdr>
0587     struct check_arguments<Tup, Car, Cdr...>
0588     {
0589         BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
0590         {
0591             return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
0592         }
0593     };
0594 }
0595 
0596 ////////////////////////////////////////
0597 
0598 namespace leaf_detail
0599 {
0600     template <class>
0601     struct handler_matches_any_error: std::false_type
0602     {
0603     };
0604 
0605     template <template<class...> class L>
0606     struct handler_matches_any_error<L<>>: std::true_type
0607     {
0608     };
0609 
0610     template <template<class...> class L, class Car, class... Cdr>
0611     struct handler_matches_any_error<L<Car, Cdr...>>
0612     {
0613         constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
0614     };
0615 }
0616 
0617 ////////////////////////////////////////
0618 
0619 namespace leaf_detail
0620 {
0621     template <class Tup, class... A>
0622     BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
0623     {
0624         return check_arguments<Tup, A...>::check(tup, ei);
0625     }
0626 
0627     template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
0628     struct handler_caller
0629     {
0630         template <class Tup, class... A>
0631         BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
0632         {
0633             return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
0634         }
0635     };
0636 
0637     template <template <class...> class Result, class... E, class F>
0638     struct handler_caller<Result<void, E...>, F, true, void>
0639     {
0640         using R = Result<void, E...>;
0641 
0642         template <class Tup, class... A>
0643         BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
0644         {
0645             std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
0646             return { };
0647         }
0648     };
0649 
0650     template <class T>
0651     struct is_tuple: std::false_type { };
0652 
0653     template <class... T>
0654     struct is_tuple<std::tuple<T...>>: std::true_type { };
0655 
0656     template <class... T>
0657     struct is_tuple<std::tuple<T...> &>: std::true_type { };
0658 
0659     template <class R, class Tup, class H>
0660     BOOST_LEAF_CONSTEXPR inline
0661     typename std::enable_if<!is_tuple<typename std::decay<H>::type>::value, R>::type
0662     handle_error_( Tup & tup, error_info const & ei, H && h )
0663     {
0664         static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
0665         return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
0666     }
0667 
0668     template <class R, class Tup, class Car, class... Cdr>
0669     BOOST_LEAF_CONSTEXPR inline
0670     typename std::enable_if<!is_tuple<typename std::decay<Car>::type>::value, R>::type
0671     handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
0672     {
0673         if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
0674             return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
0675         else
0676             return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
0677     }
0678 
0679     template <class R, class Tup, class HTup, size_t ... I>
0680     BOOST_LEAF_CONSTEXPR inline
0681     R
0682     handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
0683     {
0684         return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
0685     }
0686 
0687     template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
0688     BOOST_LEAF_CONSTEXPR inline
0689     R
0690     handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
0691     {
0692         return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
0693     }
0694 
0695     template <class R, class Tup, class H>
0696     BOOST_LEAF_CONSTEXPR inline
0697     typename std::enable_if<is_tuple<typename std::decay<H>::type>::value, R>::type
0698     handle_error_( Tup & tup, error_info const & ei, H && h )
0699     {
0700         return handle_error_tuple_<R>(
0701             tup,
0702             ei,
0703             leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
0704             std::forward<H>(h));
0705     }
0706 
0707     template <class R, class Tup, class Car, class... Cdr>
0708     BOOST_LEAF_CONSTEXPR inline
0709     typename std::enable_if<is_tuple<typename std::decay<Car>::type>::value, R>::type
0710     handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
0711     {
0712         return handle_error_tuple_<R>(
0713             tup,
0714             ei,
0715             leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
0716             std::forward<Car>(car),
0717             std::forward<Cdr>(cdr)...);
0718     }
0719 }
0720 
0721 ////////////////////////////////////////
0722 
0723 template <class... E>
0724 template <class R, class... H>
0725 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
0726 R
0727 context<E...>::
0728 handle_error( error_id id, H && ... h ) const
0729 {
0730     BOOST_LEAF_ASSERT(!is_active());
0731     return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
0732 }
0733 
0734 template <class... E>
0735 template <class R, class... H>
0736 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
0737 R
0738 context<E...>::
0739 handle_error( error_id id, H && ... h )
0740 {
0741     BOOST_LEAF_ASSERT(!is_active());
0742     return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
0743 }
0744 
0745 ////////////////////////////////////////
0746 
0747 namespace leaf_detail
0748 {
0749     template <class T>
0750     void unload_result( result<T> * r )
0751     {
0752         (void) r->unload();
0753     }
0754 
0755     inline void unload_result( void * )
0756     {
0757     }
0758 }
0759 
0760 ////////////////////////////////////////
0761 
0762 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0763 
0764 template <class TryBlock, class... H>
0765 BOOST_LEAF_CONSTEXPR inline
0766 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
0767 try_handle_all( TryBlock && try_block, H && ... h ) noexcept
0768 {
0769     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");
0770     context_type_from_handlers<H...> ctx;
0771     auto active_context = activate_context(ctx);
0772     if( auto r = std::forward<TryBlock>(try_block)() )
0773         return std::move(r).value();
0774     else
0775     {
0776         leaf_detail::unload_result(&r);
0777         error_id id = r.error();
0778         ctx.deactivate();
0779         using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
0780         return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
0781     }
0782 }
0783 
0784 template <class TryBlock, class... H>
0785 BOOST_LEAF_ATTRIBUTE_NODISCARD BOOST_LEAF_CONSTEXPR inline
0786 typename std::decay<decltype(std::declval<TryBlock>()())>::type
0787 try_handle_some( TryBlock && try_block, H && ... h ) noexcept
0788 {
0789     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");
0790     context_type_from_handlers<H...> ctx;
0791     auto active_context = activate_context(ctx);
0792     if( auto r = std::forward<TryBlock>(try_block)() )
0793         return r;
0794     else
0795     {
0796         leaf_detail::unload_result(&r);
0797         error_id id = r.error();
0798         ctx.deactivate();
0799         using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
0800         auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
0801         if( !rr )
0802             ctx.unload(rr.error());
0803         return rr;
0804     }
0805 }
0806 
0807 template <class TryBlock, class... H>
0808 BOOST_LEAF_CONSTEXPR inline
0809 decltype(std::declval<TryBlock>()())
0810 try_catch( TryBlock && try_block, H && ... ) noexcept
0811 {
0812     static_assert(sizeof(context_type_from_handlers<H...>) > 0,
0813         "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.");
0814     return std::forward<TryBlock>(try_block)();
0815 }
0816 
0817 #else
0818 
0819 namespace leaf_detail
0820 {
0821     template <class Ctx, class TryBlock, class... H>
0822     decltype(std::declval<TryBlock>()())
0823     try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
0824     {
0825         using namespace leaf_detail;
0826         BOOST_LEAF_ASSERT(ctx.is_active());
0827         using R = decltype(std::declval<TryBlock>()());
0828         try
0829         {
0830             auto r = std::forward<TryBlock>(try_block)();
0831             unload_result(&r);
0832             return std::move(r);
0833         }
0834         catch( std::exception & ex )
0835         {
0836             ctx.deactivate();
0837             error_info e(&ex);
0838             return handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
0839                 [&]() -> R
0840                 {
0841                     ctx.unload(e.error());
0842                     throw;
0843                 } );
0844         }
0845         catch(...)
0846         {
0847             ctx.deactivate();
0848             error_info e(nullptr);
0849             return handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
0850                 [&]() -> R
0851                 {
0852                     ctx.unload(e.error());
0853                     throw;
0854                 } );
0855         }
0856     }
0857 }
0858 
0859 template <class TryBlock, class... H>
0860 inline
0861 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
0862 try_handle_all( TryBlock && try_block, H && ... h )
0863 {
0864     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");
0865     context_type_from_handlers<H...> ctx;
0866     auto active_context = activate_context(ctx);
0867     if( auto r = leaf_detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
0868         return std::move(r).value();
0869     else
0870     {
0871         BOOST_LEAF_ASSERT(ctx.is_active());
0872         leaf_detail::unload_result(&r);
0873         error_id id = r.error();
0874         ctx.deactivate();
0875         using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
0876         return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
0877     }
0878 }
0879 
0880 template <class TryBlock, class... H>
0881 BOOST_LEAF_ATTRIBUTE_NODISCARD inline
0882 typename std::decay<decltype(std::declval<TryBlock>()())>::type
0883 try_handle_some( TryBlock && try_block, H && ... h )
0884 {
0885     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");
0886     context_type_from_handlers<H...> ctx;
0887     auto active_context = activate_context(ctx);
0888     if( auto r = leaf_detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
0889         return r;
0890     else if( ctx.is_active() )
0891     {
0892         leaf_detail::unload_result(&r);
0893         error_id id = r.error();
0894         ctx.deactivate();
0895         using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
0896         auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...,
0897             [&r]()->R
0898             {
0899                 return std::move(r);
0900             });
0901         if( !rr )
0902             ctx.unload(rr.error());
0903         return rr;
0904     }
0905     else
0906     {
0907         ctx.unload(r.error());
0908         return r;
0909     }
0910 }
0911 
0912 template <class TryBlock, class... H>
0913 inline
0914 decltype(std::declval<TryBlock>()())
0915 try_catch( TryBlock && try_block, H && ... h )
0916 {
0917     context_type_from_handlers<H...> ctx;
0918     auto active_context = activate_context(ctx);
0919     using R = decltype(std::declval<TryBlock>()());
0920     try
0921     {
0922         return std::forward<TryBlock>(try_block)();
0923     }
0924     catch( std::exception & ex )
0925     {
0926         ctx.deactivate();
0927         error_info e(&ex);
0928         return leaf_detail::handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
0929             [&]() -> R
0930             {
0931                 ctx.unload(e.error());
0932                 throw;
0933             } );
0934     }
0935     catch(...)
0936     {
0937         ctx.deactivate();
0938         error_info e(nullptr);
0939         return leaf_detail::handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
0940             [&]() -> R
0941             {
0942                 ctx.unload(e.error());
0943                 throw;
0944             } );
0945     }
0946 }
0947 
0948 #endif
0949 
0950 #if BOOST_LEAF_CFG_CAPTURE
0951 
0952 namespace leaf_detail
0953 {
0954     template <class LeafResult>
0955     struct try_capture_all_dispatch_non_void
0956     {
0957         using leaf_result = LeafResult;
0958 
0959         template <class TryBlock>
0960         inline
0961         static
0962         leaf_result
0963         try_capture_all_( TryBlock && try_block ) noexcept
0964         {
0965             leaf_detail::slot<leaf_detail::dynamic_allocator> sl;
0966             sl.activate();
0967 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0968             try
0969 #endif
0970             {
0971                 if( leaf_result r = std::forward<TryBlock>(try_block)() )
0972                 {
0973                     sl.deactivate();
0974                     return r;
0975                 }
0976                 else
0977                 {
0978                     sl.deactivate();
0979                     int const err_id = error_id(r.error()).value();
0980                     return leaf_result(sl.value(err_id).template extract_capture_list<leaf_result>(err_id));
0981                 }
0982             }
0983 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0984             catch( std::exception & ex )
0985             {
0986                 sl.deactivate();
0987                 int const err_id = error_info(&ex).error().value();
0988                 return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
0989             }
0990             catch(...)
0991             {
0992                 sl.deactivate();
0993                 int const err_id = error_info(nullptr).error().value();
0994                 return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
0995             }
0996 #endif
0997         }
0998     };
0999 
1000     template <class R, bool IsVoid = std::is_same<void, R>::value, bool IsResultType = is_result_type<R>::value>
1001     struct try_capture_all_dispatch;
1002 
1003     template <class R>
1004     struct try_capture_all_dispatch<R, false, true>:
1005         try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::decay<decltype(std::declval<R>().value())>::type>>
1006     {
1007     };
1008 
1009     template <class R>
1010     struct try_capture_all_dispatch<R, false, false>:
1011         try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::remove_reference<R>::type>>
1012     {
1013     };
1014 
1015     template <class R>
1016     struct try_capture_all_dispatch<R, true, false>
1017     {
1018         using leaf_result = ::boost::leaf::result<R>;
1019 
1020         template <class TryBlock>
1021         inline
1022         static
1023         leaf_result
1024         try_capture_all_( TryBlock && try_block ) noexcept
1025         {
1026             leaf_detail::slot<leaf_detail::dynamic_allocator> sl;
1027             sl.activate();
1028 #ifndef BOOST_LEAF_NO_EXCEPTIONS
1029             try
1030 #endif
1031             {
1032                 std::forward<TryBlock>(try_block)();
1033                 return {};
1034             }
1035 #ifndef BOOST_LEAF_NO_EXCEPTIONS
1036             catch( std::exception & ex )
1037             {
1038                 sl.deactivate();
1039                 int const err_id = error_info(&ex).error().value();
1040                 return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
1041             }
1042             catch(...)
1043             {
1044                 sl.deactivate();
1045                 int const err_id = error_info(nullptr).error().value();
1046                 return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
1047             }
1048 #endif
1049         }
1050     };
1051 }
1052 
1053 template <class TryBlock>
1054 inline
1055 typename leaf_detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::leaf_result
1056 try_capture_all( TryBlock && try_block ) noexcept
1057 {
1058     return leaf_detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::try_capture_all_(std::forward<TryBlock>(try_block));
1059 }
1060 #endif
1061 
1062 } }
1063 
1064 // Boost Exception Integration
1065 
1066 namespace boost { class exception; }
1067 namespace boost { template <class Tag,class T> class error_info; }
1068 namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
1069 
1070 namespace boost { namespace leaf {
1071 
1072 namespace leaf_detail
1073 {
1074     template <class T>
1075     struct match_enum_type;
1076 
1077     template <class Tag, class T>
1078     struct match_enum_type<boost::error_info<Tag, T>>
1079     {
1080         using type = T;
1081     };
1082 
1083     template <class Ex>
1084     BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
1085     {
1086         return dynamic_cast<Ex *>(ei.exception());
1087     }
1088 
1089     template <class, class T>
1090     struct dependent_type { using type = T; };
1091 
1092     template <class Dep, class T>
1093     using dependent_type_t = typename dependent_type<Dep, T>::type;
1094 
1095     template <class Tag, class T>
1096     struct handler_argument_traits<boost::error_info<Tag, T>>
1097     {
1098         using error_type = void;
1099         constexpr static bool always_available = false;
1100 
1101         template <class Tup>
1102         BOOST_LEAF_CONSTEXPR static T * check( Tup &, error_info const & ei ) noexcept
1103         {
1104             using boost_exception = dependent_type_t<T, boost::exception>;
1105             if( auto * be = get_exception<boost_exception>(ei) )
1106                 return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
1107             else
1108                 return nullptr;
1109         }
1110 
1111         template <class Tup>
1112         BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
1113         {
1114             return boost::error_info<Tag, T>(*check(tup, ei));
1115         }
1116     };
1117 
1118     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>> { };
1119     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>> { };
1120     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>> { };
1121     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>> { };
1122 }
1123 
1124 } }
1125 
1126 #endif