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