Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:53

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