handle_errors.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
  2. #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
  3. /// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
  4. /// Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. /// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_LEAF_ENABLE_WARNINGS ///
  7. # if defined(_MSC_VER) ///
  8. # pragma warning(push,1) ///
  9. # elif defined(__clang__) ///
  10. # pragma clang system_header ///
  11. # elif (__GNUC__*100+__GNUC_MINOR__>301) ///
  12. # pragma GCC system_header ///
  13. # endif ///
  14. #endif ///
  15. #include <boost/leaf/context.hpp>
  16. #include <boost/leaf/detail/demangle.hpp>
  17. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  18. # include <boost/leaf/capture.hpp>
  19. #endif
  20. namespace boost { namespace leaf {
  21. class error_info
  22. {
  23. error_info & operator=( error_info const & ) = delete;
  24. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  25. static error_id unpack_error_id( std::exception const * ex ) noexcept
  26. {
  27. if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
  28. if( is_error_id(se->code()) )
  29. return leaf_detail::make_error_id(se->code().value());
  30. if( std::error_code const * ec = dynamic_cast<std::error_code const *>(ex) )
  31. if( is_error_id(*ec) )
  32. return leaf_detail::make_error_id(ec->value());
  33. if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
  34. return *err_id;
  35. return current_error();
  36. }
  37. std::exception * const ex_;
  38. #endif
  39. error_id const err_id_;
  40. protected:
  41. error_info( error_info const & ) noexcept = default;
  42. template <class CharT, class Traits>
  43. void print( std::basic_ostream<CharT, Traits> & os ) const
  44. {
  45. os << "Error ID = " << err_id_.value();
  46. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  47. if( ex_ )
  48. {
  49. os <<
  50. "\nException dynamic type: " << leaf_detail::demangle(typeid(*ex_).name()) <<
  51. "\nstd::exception::what(): " << ex_->what();
  52. }
  53. #endif
  54. }
  55. public:
  56. BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
  57. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  58. ex_(0),
  59. #endif
  60. err_id_(id)
  61. {
  62. }
  63. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  64. explicit error_info( std::exception * ex ) noexcept:
  65. ex_(ex),
  66. err_id_(unpack_error_id(ex_))
  67. {
  68. }
  69. #endif
  70. BOOST_LEAF_CONSTEXPR error_id error() const noexcept
  71. {
  72. return err_id_;
  73. }
  74. BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
  75. {
  76. #ifdef BOOST_LEAF_NO_EXCEPTIONS
  77. return nullptr;
  78. #else
  79. return ex_;
  80. #endif
  81. }
  82. template <class CharT, class Traits>
  83. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_info const & x )
  84. {
  85. os << "leaf::error_info: ";
  86. x.print(os);
  87. return os << '\n';
  88. }
  89. };
  90. ////////////////////////////////////////
  91. #if BOOST_LEAF_DIAGNOSTICS
  92. class diagnostic_info: public error_info
  93. {
  94. leaf_detail::e_unexpected_count const * e_uc_;
  95. void const * tup_;
  96. void (*print_)( std::ostream &, void const * tup, int key_to_print );
  97. protected:
  98. diagnostic_info( diagnostic_info const & ) noexcept = default;
  99. template <class Tup>
  100. BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
  101. error_info(ei),
  102. e_uc_(e_uc),
  103. tup_(&tup),
  104. print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
  105. {
  106. }
  107. public:
  108. template <class CharT, class Traits>
  109. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
  110. {
  111. os << "leaf::diagnostic_info for ";
  112. x.print(os);
  113. os << ":\n";
  114. x.print_(os, x.tup_, x.error().value());
  115. if( x.e_uc_ )
  116. x.e_uc_->print(os);
  117. return os;
  118. }
  119. };
  120. namespace leaf_detail
  121. {
  122. struct diagnostic_info_: diagnostic_info
  123. {
  124. template <class Tup>
  125. BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
  126. diagnostic_info(ei, e_uc, tup)
  127. {
  128. }
  129. };
  130. template <>
  131. struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<e_unexpected_count>
  132. {
  133. template <class Tup>
  134. BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  135. {
  136. return diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_count>::check(tup, ei), tup);
  137. }
  138. };
  139. }
  140. #else
  141. class diagnostic_info: public error_info
  142. {
  143. protected:
  144. diagnostic_info( diagnostic_info const & ) noexcept = default;
  145. BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
  146. error_info(ei)
  147. {
  148. }
  149. public:
  150. template <class CharT, class Traits>
  151. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
  152. {
  153. os <<
  154. "leaf::diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
  155. "leaf::error_info: ";
  156. x.print(os);
  157. return os << '\n';
  158. }
  159. };
  160. namespace leaf_detail
  161. {
  162. struct diagnostic_info_: diagnostic_info
  163. {
  164. BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
  165. diagnostic_info(ei)
  166. {
  167. }
  168. };
  169. template <>
  170. struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
  171. {
  172. template <class Tup>
  173. BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  174. {
  175. return diagnostic_info_(ei);
  176. }
  177. };
  178. }
  179. #endif
  180. ////////////////////////////////////////
  181. #if BOOST_LEAF_DIAGNOSTICS
  182. class verbose_diagnostic_info: public error_info
  183. {
  184. leaf_detail::e_unexpected_info const * e_ui_;
  185. void const * tup_;
  186. void (*print_)( std::ostream &, void const * tup, int key_to_print );
  187. protected:
  188. verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
  189. template <class Tup>
  190. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
  191. error_info(ei),
  192. e_ui_(e_ui),
  193. tup_(&tup),
  194. print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
  195. {
  196. }
  197. public:
  198. template <class CharT, class Traits>
  199. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
  200. {
  201. os << "leaf::verbose_diagnostic_info for ";
  202. x.print(os);
  203. os << ":\n";
  204. x.print_(os, x.tup_, x.error().value());
  205. if( x.e_ui_ )
  206. x.e_ui_->print(os);
  207. return os;
  208. }
  209. };
  210. namespace leaf_detail
  211. {
  212. struct verbose_diagnostic_info_: verbose_diagnostic_info
  213. {
  214. template <class Tup>
  215. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
  216. verbose_diagnostic_info(ei, e_ui, tup)
  217. {
  218. }
  219. };
  220. template <>
  221. struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<e_unexpected_info>
  222. {
  223. template <class Tup>
  224. BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  225. {
  226. return verbose_diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_info>::check(tup, ei), tup);
  227. }
  228. };
  229. }
  230. #else
  231. class verbose_diagnostic_info: public error_info
  232. {
  233. protected:
  234. verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
  235. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
  236. error_info(ei)
  237. {
  238. }
  239. public:
  240. template <class CharT, class Traits>
  241. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
  242. {
  243. os <<
  244. "leaf::verbose_diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
  245. "leaf::error_info: ";
  246. x.print(os);
  247. return os << '\n';
  248. }
  249. };
  250. namespace leaf_detail
  251. {
  252. struct verbose_diagnostic_info_: verbose_diagnostic_info
  253. {
  254. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
  255. verbose_diagnostic_info(ei)
  256. {
  257. }
  258. };
  259. template <>
  260. struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
  261. {
  262. template <class Tup>
  263. BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  264. {
  265. return verbose_diagnostic_info_(ei);
  266. }
  267. };
  268. }
  269. #endif
  270. ////////////////////////////////////////
  271. namespace leaf_detail
  272. {
  273. template <class T, class... List>
  274. struct type_index;
  275. template <class T, class... Cdr>
  276. struct type_index<T, T, Cdr...>
  277. {
  278. constexpr static int value = 0;
  279. };
  280. template <class T, class Car, class... Cdr>
  281. struct type_index<T, Car, Cdr...>
  282. {
  283. constexpr static int value = 1 + type_index<T,Cdr...>::value;
  284. };
  285. template <class T, class Tuple>
  286. struct tuple_type_index;
  287. template <class T, class... TupleTypes>
  288. struct tuple_type_index<T,std::tuple<TupleTypes...>>
  289. {
  290. constexpr static int value = type_index<T,TupleTypes...>::value;
  291. };
  292. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  293. template <class E, bool = std::is_class<E>::value>
  294. struct peek_exception;
  295. template <>
  296. struct peek_exception<std::exception const, true>
  297. {
  298. BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
  299. {
  300. return ei.exception();
  301. }
  302. };
  303. template <>
  304. struct peek_exception<std::exception, true>
  305. {
  306. BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
  307. {
  308. return ei.exception();
  309. }
  310. };
  311. template <>
  312. struct peek_exception<std::error_code const, true>
  313. {
  314. static std::error_code const * peek( error_info const & ei ) noexcept
  315. {
  316. auto const ex = ei.exception();
  317. if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
  318. return &se->code();
  319. else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
  320. return ec;
  321. else
  322. return 0;
  323. }
  324. };
  325. template <>
  326. struct peek_exception<std::error_code, true>
  327. {
  328. static std::error_code * peek( error_info const & ei ) noexcept
  329. {
  330. auto const ex = ei.exception();
  331. if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
  332. return const_cast<std::error_code *>(&se->code());
  333. else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
  334. return ec;
  335. else
  336. return 0;
  337. }
  338. };
  339. template <class E>
  340. struct peek_exception<E, true>
  341. {
  342. static E * peek( error_info const & ei ) noexcept
  343. {
  344. return dynamic_cast<E *>(ei.exception());
  345. }
  346. };
  347. template <class E>
  348. struct peek_exception<E, false>
  349. {
  350. BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
  351. {
  352. return 0;
  353. }
  354. };
  355. #endif
  356. template <class E, class SlotsTuple>
  357. BOOST_LEAF_CONSTEXPR inline
  358. E const *
  359. peek( SlotsTuple const & tup, error_info const & ei ) noexcept
  360. {
  361. if( error_id err = ei.error() )
  362. if( E const * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
  363. return e;
  364. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  365. else
  366. return peek_exception<E const>::peek(ei);
  367. #endif
  368. return 0;
  369. }
  370. template <class E, class SlotsTuple>
  371. BOOST_LEAF_CONSTEXPR inline
  372. E *
  373. peek( SlotsTuple & tup, error_info const & ei ) noexcept
  374. {
  375. if( error_id err = ei.error() )
  376. if( E * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
  377. return e;
  378. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  379. else
  380. return peek_exception<E>::peek(ei);
  381. #endif
  382. return 0;
  383. }
  384. }
  385. ////////////////////////////////////////
  386. namespace leaf_detail
  387. {
  388. template <class A>
  389. template <class Tup>
  390. BOOST_LEAF_CONSTEXPR inline
  391. typename handler_argument_traits_defaults<A, false>::error_type const *
  392. handler_argument_traits_defaults<A, false>::
  393. check( Tup const & tup, error_info const & ei ) noexcept
  394. {
  395. return peek<typename std::decay<A>::type>(tup, ei);
  396. }
  397. template <class A>
  398. template <class Tup>
  399. BOOST_LEAF_CONSTEXPR inline
  400. typename handler_argument_traits_defaults<A, false>::error_type *
  401. handler_argument_traits_defaults<A, false>::
  402. check( Tup & tup, error_info const & ei ) noexcept
  403. {
  404. return peek<typename std::decay<A>::type>(tup, ei);
  405. }
  406. template <class Tup>
  407. BOOST_LEAF_CONSTEXPR inline
  408. std::exception const *
  409. handler_argument_traits<void>::
  410. check( Tup const &, error_info const & ei ) noexcept
  411. {
  412. return ei.exception();
  413. }
  414. template <class Tup, class... List>
  415. struct check_arguments;
  416. template <class Tup>
  417. struct check_arguments<Tup>
  418. {
  419. BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
  420. {
  421. return true;
  422. }
  423. };
  424. template <class Tup, class Car, class... Cdr>
  425. struct check_arguments<Tup, Car, Cdr...>
  426. {
  427. BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
  428. {
  429. return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
  430. }
  431. };
  432. }
  433. ////////////////////////////////////////
  434. namespace leaf_detail
  435. {
  436. template <class>
  437. struct handler_matches_any_error: std::false_type
  438. {
  439. };
  440. template <template<class...> class L>
  441. struct handler_matches_any_error<L<>>: std::true_type
  442. {
  443. };
  444. template <template<class...> class L, class Car, class... Cdr>
  445. struct handler_matches_any_error<L<Car, Cdr...>>
  446. {
  447. constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
  448. };
  449. }
  450. ////////////////////////////////////////
  451. namespace leaf_detail
  452. {
  453. template <class Tup, class... A>
  454. BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
  455. {
  456. return check_arguments<Tup, A...>::check(tup, ei);
  457. }
  458. template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
  459. struct handler_caller
  460. {
  461. template <class Tup, class... A>
  462. BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
  463. {
  464. return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
  465. }
  466. };
  467. template <template <class...> class Result, class... E, class F>
  468. struct handler_caller<Result<void, E...>, F, true, void>
  469. {
  470. using R = Result<void, E...>;
  471. template <class Tup, class... A>
  472. BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
  473. {
  474. std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
  475. return { };
  476. }
  477. };
  478. template <class T>
  479. struct is_tuple: std::false_type { };
  480. template <class... T>
  481. struct is_tuple<std::tuple<T...>>: std::true_type { };
  482. template <class... T>
  483. struct is_tuple<std::tuple<T...> &>: std::true_type { };
  484. template <class R, class Tup, class H>
  485. BOOST_LEAF_CONSTEXPR inline
  486. typename std::enable_if<!is_tuple<H>::value, R>::type
  487. handle_error_( Tup & tup, error_info const & ei, H && h )
  488. {
  489. static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
  490. return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
  491. }
  492. template <class R, class Tup, class Car, class... Cdr>
  493. BOOST_LEAF_CONSTEXPR inline
  494. typename std::enable_if<!is_tuple<Car>::value, R>::type
  495. handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
  496. {
  497. if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
  498. return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
  499. else
  500. return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
  501. }
  502. template <class R, class Tup, class HTup, size_t ... I>
  503. BOOST_LEAF_CONSTEXPR inline
  504. R
  505. handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
  506. {
  507. return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
  508. }
  509. template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
  510. BOOST_LEAF_CONSTEXPR inline
  511. R
  512. handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
  513. {
  514. return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
  515. }
  516. template <class R, class Tup, class H>
  517. BOOST_LEAF_CONSTEXPR inline
  518. typename std::enable_if<is_tuple<H>::value, R>::type
  519. handle_error_( Tup & tup, error_info const & ei, H && h )
  520. {
  521. return handle_error_tuple_<R>(
  522. tup,
  523. ei,
  524. leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
  525. std::forward<H>(h));
  526. }
  527. template <class R, class Tup, class Car, class... Cdr>
  528. BOOST_LEAF_CONSTEXPR inline
  529. typename std::enable_if<is_tuple<Car>::value, R>::type
  530. handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
  531. {
  532. return handle_error_tuple_<R>(
  533. tup,
  534. ei,
  535. leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
  536. std::forward<Car>(car),
  537. std::forward<Cdr>(cdr)...);
  538. }
  539. }
  540. ////////////////////////////////////////
  541. template <class... E>
  542. template <class R, class... H>
  543. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
  544. R
  545. context<E...>::
  546. handle_error( error_id id, H && ... h ) const
  547. {
  548. BOOST_LEAF_ASSERT(!is_active());
  549. return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
  550. }
  551. template <class... E>
  552. template <class R, class... H>
  553. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
  554. R
  555. context<E...>::
  556. handle_error( error_id id, H && ... h )
  557. {
  558. BOOST_LEAF_ASSERT(!is_active());
  559. return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
  560. }
  561. ////////////////////////////////////////
  562. #ifdef BOOST_LEAF_NO_EXCEPTIONS
  563. template <class TryBlock, class... H>
  564. BOOST_LEAF_CONSTEXPR inline
  565. typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
  566. try_handle_all( TryBlock && try_block, H && ... h ) noexcept
  567. {
  568. 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");
  569. context_type_from_handlers<H...> ctx;
  570. auto active_context = activate_context(ctx);
  571. if( auto r = std::forward<TryBlock>(try_block)() )
  572. return std::move(r).value();
  573. else
  574. {
  575. error_id id = r.error();
  576. ctx.deactivate();
  577. using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
  578. return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
  579. }
  580. }
  581. template <class TryBlock, class... H>
  582. BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
  583. typename std::decay<decltype(std::declval<TryBlock>()())>::type
  584. try_handle_some( TryBlock && try_block, H && ... h ) noexcept
  585. {
  586. 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");
  587. context_type_from_handlers<H...> ctx;
  588. auto active_context = activate_context(ctx);
  589. if( auto r = std::forward<TryBlock>(try_block)() )
  590. return r;
  591. else
  592. {
  593. error_id id = r.error();
  594. ctx.deactivate();
  595. using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
  596. auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
  597. if( !rr )
  598. ctx.propagate();
  599. return rr;
  600. }
  601. }
  602. template <class TryBlock, class... H>
  603. BOOST_LEAF_CONSTEXPR inline
  604. decltype(std::declval<TryBlock>()())
  605. try_catch( TryBlock && try_block, H && ... ) noexcept
  606. {
  607. static_assert(sizeof(context_type_from_handlers<H...>) > 0,
  608. "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.");
  609. return std::forward<TryBlock>(try_block)();
  610. }
  611. #else
  612. namespace leaf_detail
  613. {
  614. template <class Ctx, class TryBlock, class... H>
  615. decltype(std::declval<TryBlock>()())
  616. try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
  617. {
  618. using namespace leaf_detail;
  619. BOOST_LEAF_ASSERT(ctx.is_active());
  620. using R = decltype(std::declval<TryBlock>()());
  621. try
  622. {
  623. return std::forward<TryBlock>(try_block)();
  624. }
  625. catch( capturing_exception const & cap )
  626. {
  627. try
  628. {
  629. cap.unload_and_rethrow_original_exception();
  630. }
  631. catch( std::exception & ex )
  632. {
  633. ctx.deactivate();
  634. return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
  635. []() -> R { throw; } );
  636. }
  637. catch(...)
  638. {
  639. ctx.deactivate();
  640. return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
  641. []() -> R { throw; } );
  642. }
  643. }
  644. catch( std::exception & ex )
  645. {
  646. ctx.deactivate();
  647. return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
  648. []() -> R { throw; } );
  649. }
  650. catch(...)
  651. {
  652. ctx.deactivate();
  653. return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
  654. []() -> R { throw; } );
  655. }
  656. }
  657. }
  658. template <class TryBlock, class... H>
  659. BOOST_LEAF_CONSTEXPR inline
  660. typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
  661. try_handle_all( TryBlock && try_block, H && ... h )
  662. {
  663. 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");
  664. context_type_from_handlers<H...> ctx;
  665. auto active_context = activate_context(ctx);
  666. if( auto r = leaf_detail::try_catch_(
  667. ctx,
  668. [&]
  669. {
  670. return std::forward<TryBlock>(try_block)();
  671. },
  672. std::forward<H>(h)...) )
  673. return std::move(r).value();
  674. else
  675. {
  676. error_id id = r.error();
  677. if( ctx.is_active() )
  678. ctx.deactivate();
  679. using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
  680. return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
  681. }
  682. }
  683. template <class TryBlock, class... H>
  684. BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
  685. typename std::decay<decltype(std::declval<TryBlock>()())>::type
  686. try_handle_some( TryBlock && try_block, H && ... h )
  687. {
  688. 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");
  689. context_type_from_handlers<H...> ctx;
  690. auto active_context = activate_context(ctx);
  691. if( auto r = leaf_detail::try_catch_(
  692. ctx,
  693. [&]
  694. {
  695. return std::forward<TryBlock>(try_block)();
  696. },
  697. std::forward<H>(h)...) )
  698. return r;
  699. else
  700. {
  701. error_id id = r.error();
  702. if( ctx.is_active() )
  703. ctx.deactivate();
  704. using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
  705. auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
  706. if( !rr )
  707. ctx.propagate();
  708. return rr;
  709. }
  710. }
  711. template <class TryBlock, class... H>
  712. BOOST_LEAF_CONSTEXPR inline
  713. decltype(std::declval<TryBlock>()())
  714. try_catch( TryBlock && try_block, H && ... h )
  715. {
  716. context_type_from_handlers<H...> ctx;
  717. auto active_context = activate_context(ctx);
  718. return leaf_detail::try_catch_(
  719. ctx,
  720. [&]
  721. {
  722. return std::forward<TryBlock>(try_block)();
  723. },
  724. std::forward<H>(h)...);
  725. }
  726. #endif
  727. } }
  728. // Boost Exception Integration
  729. namespace boost { class exception; }
  730. namespace boost { template <class Tag,class T> class error_info; }
  731. namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
  732. namespace boost { namespace leaf {
  733. namespace leaf_detail
  734. {
  735. template <class T>
  736. struct match_enum_type;
  737. template <class Tag, class T>
  738. struct match_enum_type<boost::error_info<Tag, T>>
  739. {
  740. using type = T;
  741. };
  742. template <class Ex>
  743. BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
  744. {
  745. return dynamic_cast<Ex *>(ei.exception());
  746. }
  747. template <class, class T>
  748. struct dependent_type { using type = T; };
  749. template <class Dep, class T>
  750. using dependent_type_t = typename dependent_type<Dep, T>::type;
  751. template <class Tag, class T>
  752. struct handler_argument_traits<boost::error_info<Tag, T>>
  753. {
  754. using error_type = void;
  755. constexpr static bool always_available = false;
  756. template <class Tup>
  757. BOOST_LEAF_CONSTEXPR static T * check( Tup & tup, error_info const & ei ) noexcept
  758. {
  759. using boost_exception = dependent_type_t<T, boost::exception>;
  760. if( auto * be = get_exception<boost_exception>(ei) )
  761. return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
  762. else
  763. return 0;
  764. }
  765. template <class Tup>
  766. BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
  767. {
  768. return boost::error_info<Tag, T>(*check(tup, ei));
  769. }
  770. };
  771. 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>> { };
  772. 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>> { };
  773. 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>> { };
  774. 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>> { };
  775. }
  776. } }
  777. #if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
  778. #pragma warning(pop) ///
  779. #endif ///
  780. #endif