123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910 |
- #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
- #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
- /// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
- /// Distributed under the Boost Software License, Version 1.0. (See accompanying
- /// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_LEAF_ENABLE_WARNINGS ///
- # if defined(_MSC_VER) ///
- # pragma warning(push,1) ///
- # elif defined(__clang__) ///
- # pragma clang system_header ///
- # elif (__GNUC__*100+__GNUC_MINOR__>301) ///
- # pragma GCC system_header ///
- # endif ///
- #endif ///
- #include <boost/leaf/context.hpp>
- #include <boost/leaf/detail/demangle.hpp>
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- # include <boost/leaf/capture.hpp>
- #endif
- namespace boost { namespace leaf {
- class error_info
- {
- error_info & operator=( error_info const & ) = delete;
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- static error_id unpack_error_id( std::exception const * ex ) noexcept
- {
- if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
- if( is_error_id(se->code()) )
- return leaf_detail::make_error_id(se->code().value());
- if( std::error_code const * ec = dynamic_cast<std::error_code const *>(ex) )
- if( is_error_id(*ec) )
- return leaf_detail::make_error_id(ec->value());
- if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
- return *err_id;
- return current_error();
- }
- std::exception * const ex_;
- #endif
- error_id const err_id_;
- protected:
- error_info( error_info const & ) noexcept = default;
- template <class CharT, class Traits>
- void print( std::basic_ostream<CharT, Traits> & os ) const
- {
- os << "Error ID = " << err_id_.value();
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- if( ex_ )
- {
- os <<
- "\nException dynamic type: " << leaf_detail::demangle(typeid(*ex_).name()) <<
- "\nstd::exception::what(): " << ex_->what();
- }
- #endif
- }
- public:
- BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- ex_(0),
- #endif
- err_id_(id)
- {
- }
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- explicit error_info( std::exception * ex ) noexcept:
- ex_(ex),
- err_id_(unpack_error_id(ex_))
- {
- }
- #endif
- BOOST_LEAF_CONSTEXPR error_id error() const noexcept
- {
- return err_id_;
- }
- BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
- {
- #ifdef BOOST_LEAF_NO_EXCEPTIONS
- return nullptr;
- #else
- return ex_;
- #endif
- }
- template <class CharT, class Traits>
- friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_info const & x )
- {
- os << "leaf::error_info: ";
- x.print(os);
- return os << '\n';
- }
- };
- ////////////////////////////////////////
- #if BOOST_LEAF_DIAGNOSTICS
- class diagnostic_info: public error_info
- {
- leaf_detail::e_unexpected_count const * e_uc_;
- void const * tup_;
- void (*print_)( std::ostream &, void const * tup, int key_to_print );
- protected:
- diagnostic_info( diagnostic_info const & ) noexcept = default;
- template <class Tup>
- BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
- error_info(ei),
- e_uc_(e_uc),
- tup_(&tup),
- print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
- {
- }
- public:
- template <class CharT, class Traits>
- friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
- {
- os << "leaf::diagnostic_info for ";
- x.print(os);
- os << ":\n";
- x.print_(os, x.tup_, x.error().value());
- if( x.e_uc_ )
- x.e_uc_->print(os);
- return os;
- }
- };
- namespace leaf_detail
- {
- struct diagnostic_info_: diagnostic_info
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
- diagnostic_info(ei, e_uc, tup)
- {
- }
- };
- template <>
- struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<e_unexpected_count>
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
- {
- return diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_count>::check(tup, ei), tup);
- }
- };
- }
- #else
- class diagnostic_info: public error_info
- {
- protected:
- diagnostic_info( diagnostic_info const & ) noexcept = default;
- BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
- error_info(ei)
- {
- }
- public:
- template <class CharT, class Traits>
- friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
- {
- os <<
- "leaf::diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
- "leaf::error_info: ";
- x.print(os);
- return os << '\n';
- }
- };
- namespace leaf_detail
- {
- struct diagnostic_info_: diagnostic_info
- {
- BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
- diagnostic_info(ei)
- {
- }
- };
- template <>
- struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
- {
- return diagnostic_info_(ei);
- }
- };
- }
- #endif
- ////////////////////////////////////////
- #if BOOST_LEAF_DIAGNOSTICS
- class verbose_diagnostic_info: public error_info
- {
- leaf_detail::e_unexpected_info const * e_ui_;
- void const * tup_;
- void (*print_)( std::ostream &, void const * tup, int key_to_print );
- protected:
- verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
- template <class Tup>
- BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
- error_info(ei),
- e_ui_(e_ui),
- tup_(&tup),
- print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
- {
- }
- public:
- template <class CharT, class Traits>
- friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
- {
- os << "leaf::verbose_diagnostic_info for ";
- x.print(os);
- os << ":\n";
- x.print_(os, x.tup_, x.error().value());
- if( x.e_ui_ )
- x.e_ui_->print(os);
- return os;
- }
- };
- namespace leaf_detail
- {
- struct verbose_diagnostic_info_: verbose_diagnostic_info
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
- verbose_diagnostic_info(ei, e_ui, tup)
- {
- }
- };
- template <>
- struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<e_unexpected_info>
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
- {
- return verbose_diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_info>::check(tup, ei), tup);
- }
- };
- }
- #else
- class verbose_diagnostic_info: public error_info
- {
- protected:
- verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
- BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
- error_info(ei)
- {
- }
- public:
- template <class CharT, class Traits>
- friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
- {
- os <<
- "leaf::verbose_diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
- "leaf::error_info: ";
- x.print(os);
- return os << '\n';
- }
- };
- namespace leaf_detail
- {
- struct verbose_diagnostic_info_: verbose_diagnostic_info
- {
- BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
- verbose_diagnostic_info(ei)
- {
- }
- };
- template <>
- struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
- {
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
- {
- return verbose_diagnostic_info_(ei);
- }
- };
- }
- #endif
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class T, class... List>
- struct type_index;
- template <class T, class... Cdr>
- struct type_index<T, T, Cdr...>
- {
- constexpr static int value = 0;
- };
- template <class T, class Car, class... Cdr>
- struct type_index<T, Car, Cdr...>
- {
- constexpr static int value = 1 + type_index<T,Cdr...>::value;
- };
- template <class T, class Tuple>
- struct tuple_type_index;
- template <class T, class... TupleTypes>
- struct tuple_type_index<T,std::tuple<TupleTypes...>>
- {
- constexpr static int value = type_index<T,TupleTypes...>::value;
- };
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- template <class E, bool = std::is_class<E>::value>
- struct peek_exception;
- template <>
- struct peek_exception<std::exception const, true>
- {
- BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
- {
- return ei.exception();
- }
- };
- template <>
- struct peek_exception<std::exception, true>
- {
- BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
- {
- return ei.exception();
- }
- };
- template <>
- struct peek_exception<std::error_code const, true>
- {
- static std::error_code const * peek( error_info const & ei ) noexcept
- {
- auto const ex = ei.exception();
- if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
- return &se->code();
- else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
- return ec;
- else
- return 0;
- }
- };
- template <>
- struct peek_exception<std::error_code, true>
- {
- static std::error_code * peek( error_info const & ei ) noexcept
- {
- auto const ex = ei.exception();
- if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
- return const_cast<std::error_code *>(&se->code());
- else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
- return ec;
- else
- return 0;
- }
- };
- template <class E>
- struct peek_exception<E, true>
- {
- static E * peek( error_info const & ei ) noexcept
- {
- return dynamic_cast<E *>(ei.exception());
- }
- };
- template <class E>
- struct peek_exception<E, false>
- {
- BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
- {
- return 0;
- }
- };
- #endif
- template <class E, class SlotsTuple>
- BOOST_LEAF_CONSTEXPR inline
- E const *
- peek( SlotsTuple const & tup, error_info const & ei ) noexcept
- {
- if( error_id err = ei.error() )
- if( E const * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
- return e;
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- else
- return peek_exception<E const>::peek(ei);
- #endif
- return 0;
- }
- template <class E, class SlotsTuple>
- BOOST_LEAF_CONSTEXPR inline
- E *
- peek( SlotsTuple & tup, error_info const & ei ) noexcept
- {
- if( error_id err = ei.error() )
- if( E * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
- return e;
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- else
- return peek_exception<E>::peek(ei);
- #endif
- return 0;
- }
- }
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class A>
- template <class Tup>
- BOOST_LEAF_CONSTEXPR inline
- typename handler_argument_traits_defaults<A, false>::error_type const *
- handler_argument_traits_defaults<A, false>::
- check( Tup const & tup, error_info const & ei ) noexcept
- {
- return peek<typename std::decay<A>::type>(tup, ei);
- }
- template <class A>
- template <class Tup>
- BOOST_LEAF_CONSTEXPR inline
- typename handler_argument_traits_defaults<A, false>::error_type *
- handler_argument_traits_defaults<A, false>::
- check( Tup & tup, error_info const & ei ) noexcept
- {
- return peek<typename std::decay<A>::type>(tup, ei);
- }
- template <class Tup>
- BOOST_LEAF_CONSTEXPR inline
- std::exception const *
- handler_argument_traits<void>::
- check( Tup const &, error_info const & ei ) noexcept
- {
- return ei.exception();
- }
- template <class Tup, class... List>
- struct check_arguments;
- template <class Tup>
- struct check_arguments<Tup>
- {
- BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
- {
- return true;
- }
- };
- template <class Tup, class Car, class... Cdr>
- struct check_arguments<Tup, Car, Cdr...>
- {
- BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
- {
- return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
- }
- };
- }
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class>
- struct handler_matches_any_error: std::false_type
- {
- };
- template <template<class...> class L>
- struct handler_matches_any_error<L<>>: std::true_type
- {
- };
- template <template<class...> class L, class Car, class... Cdr>
- struct handler_matches_any_error<L<Car, Cdr...>>
- {
- constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
- };
- }
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class Tup, class... A>
- BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
- {
- return check_arguments<Tup, A...>::check(tup, ei);
- }
- template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
- struct handler_caller
- {
- template <class Tup, class... A>
- BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
- {
- return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
- }
- };
- template <template <class...> class Result, class... E, class F>
- struct handler_caller<Result<void, E...>, F, true, void>
- {
- using R = Result<void, E...>;
- template <class Tup, class... A>
- BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
- {
- std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
- return { };
- }
- };
- template <class T>
- struct is_tuple: std::false_type { };
- template <class... T>
- struct is_tuple<std::tuple<T...>>: std::true_type { };
- template <class... T>
- struct is_tuple<std::tuple<T...> &>: std::true_type { };
- template <class R, class Tup, class H>
- BOOST_LEAF_CONSTEXPR inline
- typename std::enable_if<!is_tuple<H>::value, R>::type
- handle_error_( Tup & tup, error_info const & ei, H && h )
- {
- static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
- return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
- }
- template <class R, class Tup, class Car, class... Cdr>
- BOOST_LEAF_CONSTEXPR inline
- typename std::enable_if<!is_tuple<Car>::value, R>::type
- handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
- {
- if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
- return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
- else
- return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
- }
- template <class R, class Tup, class HTup, size_t ... I>
- BOOST_LEAF_CONSTEXPR inline
- R
- handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
- {
- return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
- }
- template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
- BOOST_LEAF_CONSTEXPR inline
- R
- handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
- {
- return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
- }
- template <class R, class Tup, class H>
- BOOST_LEAF_CONSTEXPR inline
- typename std::enable_if<is_tuple<H>::value, R>::type
- handle_error_( Tup & tup, error_info const & ei, H && h )
- {
- return handle_error_tuple_<R>(
- tup,
- ei,
- leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
- std::forward<H>(h));
- }
- template <class R, class Tup, class Car, class... Cdr>
- BOOST_LEAF_CONSTEXPR inline
- typename std::enable_if<is_tuple<Car>::value, R>::type
- handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
- {
- return handle_error_tuple_<R>(
- tup,
- ei,
- leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
- std::forward<Car>(car),
- std::forward<Cdr>(cdr)...);
- }
- }
- ////////////////////////////////////////
- template <class... E>
- template <class R, class... H>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
- R
- context<E...>::
- handle_error( error_id id, H && ... h ) const
- {
- BOOST_LEAF_ASSERT(!is_active());
- return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
- }
- template <class... E>
- template <class R, class... H>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
- R
- context<E...>::
- handle_error( error_id id, H && ... h )
- {
- BOOST_LEAF_ASSERT(!is_active());
- return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
- }
- ////////////////////////////////////////
- #ifdef BOOST_LEAF_NO_EXCEPTIONS
- template <class TryBlock, class... H>
- BOOST_LEAF_CONSTEXPR inline
- typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
- try_handle_all( TryBlock && try_block, H && ... h ) noexcept
- {
- 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");
- context_type_from_handlers<H...> ctx;
- auto active_context = activate_context(ctx);
- if( auto r = std::forward<TryBlock>(try_block)() )
- return std::move(r).value();
- else
- {
- error_id id = r.error();
- ctx.deactivate();
- using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
- return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
- }
- }
- template <class TryBlock, class... H>
- BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
- typename std::decay<decltype(std::declval<TryBlock>()())>::type
- try_handle_some( TryBlock && try_block, H && ... h ) noexcept
- {
- 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");
- context_type_from_handlers<H...> ctx;
- auto active_context = activate_context(ctx);
- if( auto r = std::forward<TryBlock>(try_block)() )
- return r;
- else
- {
- error_id id = r.error();
- ctx.deactivate();
- using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
- auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
- if( !rr )
- ctx.propagate();
- return rr;
- }
- }
- template <class TryBlock, class... H>
- BOOST_LEAF_CONSTEXPR inline
- decltype(std::declval<TryBlock>()())
- try_catch( TryBlock && try_block, H && ... ) noexcept
- {
- static_assert(sizeof(context_type_from_handlers<H...>) > 0,
- "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.");
- return std::forward<TryBlock>(try_block)();
- }
- #else
- namespace leaf_detail
- {
- template <class Ctx, class TryBlock, class... H>
- decltype(std::declval<TryBlock>()())
- try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
- {
- using namespace leaf_detail;
- BOOST_LEAF_ASSERT(ctx.is_active());
- using R = decltype(std::declval<TryBlock>()());
- try
- {
- return std::forward<TryBlock>(try_block)();
- }
- catch( capturing_exception const & cap )
- {
- try
- {
- cap.unload_and_rethrow_original_exception();
- }
- catch( std::exception & ex )
- {
- ctx.deactivate();
- return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
- []() -> R { throw; } );
- }
- catch(...)
- {
- ctx.deactivate();
- return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
- []() -> R { throw; } );
- }
- }
- catch( std::exception & ex )
- {
- ctx.deactivate();
- return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
- []() -> R { throw; } );
- }
- catch(...)
- {
- ctx.deactivate();
- return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
- []() -> R { throw; } );
- }
- }
- }
- template <class TryBlock, class... H>
- BOOST_LEAF_CONSTEXPR inline
- typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
- try_handle_all( TryBlock && try_block, H && ... h )
- {
- 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");
- context_type_from_handlers<H...> ctx;
- auto active_context = activate_context(ctx);
- if( auto r = leaf_detail::try_catch_(
- ctx,
- [&]
- {
- return std::forward<TryBlock>(try_block)();
- },
- std::forward<H>(h)...) )
- return std::move(r).value();
- else
- {
- error_id id = r.error();
- if( ctx.is_active() )
- ctx.deactivate();
- using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
- return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
- }
- }
- template <class TryBlock, class... H>
- BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
- typename std::decay<decltype(std::declval<TryBlock>()())>::type
- try_handle_some( TryBlock && try_block, H && ... h )
- {
- 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");
- context_type_from_handlers<H...> ctx;
- auto active_context = activate_context(ctx);
- if( auto r = leaf_detail::try_catch_(
- ctx,
- [&]
- {
- return std::forward<TryBlock>(try_block)();
- },
- std::forward<H>(h)...) )
- return r;
- else
- {
- error_id id = r.error();
- if( ctx.is_active() )
- ctx.deactivate();
- using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
- auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
- if( !rr )
- ctx.propagate();
- return rr;
- }
- }
- template <class TryBlock, class... H>
- BOOST_LEAF_CONSTEXPR inline
- decltype(std::declval<TryBlock>()())
- try_catch( TryBlock && try_block, H && ... h )
- {
- context_type_from_handlers<H...> ctx;
- auto active_context = activate_context(ctx);
- return leaf_detail::try_catch_(
- ctx,
- [&]
- {
- return std::forward<TryBlock>(try_block)();
- },
- std::forward<H>(h)...);
- }
- #endif
- } }
- // Boost Exception Integration
- namespace boost { class exception; }
- namespace boost { template <class Tag,class T> class error_info; }
- namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
- namespace boost { namespace leaf {
- namespace leaf_detail
- {
- template <class T>
- struct match_enum_type;
- template <class Tag, class T>
- struct match_enum_type<boost::error_info<Tag, T>>
- {
- using type = T;
- };
- template <class Ex>
- BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
- {
- return dynamic_cast<Ex *>(ei.exception());
- }
- template <class, class T>
- struct dependent_type { using type = T; };
- template <class Dep, class T>
- using dependent_type_t = typename dependent_type<Dep, T>::type;
- template <class Tag, class T>
- struct handler_argument_traits<boost::error_info<Tag, T>>
- {
- using error_type = void;
- constexpr static bool always_available = false;
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static T * check( Tup & tup, error_info const & ei ) noexcept
- {
- using boost_exception = dependent_type_t<T, boost::exception>;
- if( auto * be = get_exception<boost_exception>(ei) )
- return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
- else
- return 0;
- }
- template <class Tup>
- BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
- {
- return boost::error_info<Tag, T>(*check(tup, ei));
- }
- };
- 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>> { };
- 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>> { };
- 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>> { };
- 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>> { };
- }
- } }
- #if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
- #pragma warning(pop) ///
- #endif ///
- #endif
|