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
0005
0006
0007
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
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