handle_errors.hpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
  2. #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
  3. // Copyright 2018-2023 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. #include <boost/leaf/config.hpp>
  7. #include <boost/leaf/context.hpp>
  8. namespace boost { namespace leaf {
  9. template <class T>
  10. class BOOST_LEAF_SYMBOL_VISIBLE result;
  11. ////////////////////////////////////////
  12. class BOOST_LEAF_SYMBOL_VISIBLE error_info
  13. {
  14. error_info & operator=( error_info const & ) = delete;
  15. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  16. static error_id unpack_error_id( std::exception const * ex ) noexcept
  17. {
  18. if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
  19. return *err_id;
  20. return current_error();
  21. }
  22. std::exception * const ex_;
  23. #endif
  24. error_id const err_id_;
  25. protected:
  26. error_info( error_info const & ) noexcept = default;
  27. public:
  28. BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
  29. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  30. ex_(nullptr),
  31. #endif
  32. err_id_(id)
  33. {
  34. }
  35. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  36. explicit error_info( std::exception * ex ) noexcept:
  37. ex_(ex),
  38. err_id_(unpack_error_id(ex_))
  39. {
  40. }
  41. #endif
  42. BOOST_LEAF_CONSTEXPR error_id error() const noexcept
  43. {
  44. return err_id_;
  45. }
  46. BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
  47. {
  48. #ifdef BOOST_LEAF_NO_EXCEPTIONS
  49. return nullptr;
  50. #else
  51. return ex_;
  52. #endif
  53. }
  54. template <class CharT, class Traits>
  55. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, error_info const & x )
  56. {
  57. os << "Error ID: " << x.err_id_.value();
  58. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  59. if( x.ex_ )
  60. {
  61. os <<
  62. "\nException dynamic type: " << leaf_detail::demangle(typeid(*x.ex_).name()) <<
  63. "\nstd::exception::what(): " << x.ex_->what();
  64. }
  65. #endif
  66. return os << '\n';
  67. }
  68. };
  69. namespace leaf_detail
  70. {
  71. template <>
  72. struct handler_argument_traits<error_info const &>: handler_argument_always_available<void>
  73. {
  74. template <class Tup>
  75. BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept
  76. {
  77. return ei;
  78. }
  79. };
  80. }
  81. ////////////////////////////////////////
  82. #if BOOST_LEAF_CFG_DIAGNOSTICS
  83. class diagnostic_info: public error_info
  84. {
  85. void const * tup_;
  86. void (*print_context_content_)( std::ostream &, void const * tup, int err_id_to_print );
  87. protected:
  88. diagnostic_info( diagnostic_info const & ) noexcept = default;
  89. template <class Tup>
  90. BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
  91. error_info(ei),
  92. tup_(&tup),
  93. print_context_content_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
  94. {
  95. }
  96. template <class CharT, class Traits>
  97. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
  98. {
  99. os << static_cast<error_info const &>(x);
  100. x.print_context_content_(os, x.tup_, x.error().value());
  101. return os;
  102. }
  103. };
  104. namespace leaf_detail
  105. {
  106. struct diagnostic_info_: diagnostic_info
  107. {
  108. template <class Tup>
  109. BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, Tup const & tup ) noexcept:
  110. diagnostic_info(ei, tup)
  111. {
  112. }
  113. };
  114. template <>
  115. struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
  116. {
  117. template <class Tup>
  118. BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  119. {
  120. return diagnostic_info_(ei, tup);
  121. }
  122. };
  123. }
  124. #else
  125. class diagnostic_info: public error_info
  126. {
  127. protected:
  128. diagnostic_info( diagnostic_info const & ) noexcept = default;
  129. BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
  130. error_info(ei)
  131. {
  132. }
  133. template <class CharT, class Traits>
  134. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
  135. {
  136. return os << "diagnostic_info not available due to BOOST_LEAF_CFG_DIAGNOSTICS=0. Basic error_info follows.\n" << static_cast<error_info const &>(x);
  137. }
  138. };
  139. namespace leaf_detail
  140. {
  141. struct diagnostic_info_: diagnostic_info
  142. {
  143. BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
  144. diagnostic_info(ei)
  145. {
  146. }
  147. };
  148. template <>
  149. struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
  150. {
  151. template <class Tup>
  152. BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const &, error_info const & ei ) noexcept
  153. {
  154. return diagnostic_info_(ei);
  155. }
  156. };
  157. }
  158. #endif
  159. ////////////////////////////////////////
  160. #if BOOST_LEAF_CFG_DIAGNOSTICS
  161. #if BOOST_LEAF_CFG_CAPTURE
  162. class verbose_diagnostic_info: public diagnostic_info
  163. {
  164. leaf_detail::dynamic_allocator const * const da_;
  165. protected:
  166. verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
  167. template <class Tup>
  168. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, Tup const & tup, leaf_detail::dynamic_allocator const * da ) noexcept:
  169. diagnostic_info(ei, tup),
  170. da_(da)
  171. {
  172. }
  173. template <class CharT, class Traits>
  174. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
  175. {
  176. os << static_cast<diagnostic_info const &>(x);
  177. if( x.da_ )
  178. x.da_->print(os, "Unhandled error objects:\n", x.error().value());
  179. return os;
  180. }
  181. };
  182. namespace leaf_detail
  183. {
  184. template <class T>
  185. struct get_dispatch
  186. {
  187. static BOOST_LEAF_CONSTEXPR T const * get(T const * x) noexcept
  188. {
  189. return x;
  190. }
  191. static BOOST_LEAF_CONSTEXPR T const * get(void const *) noexcept
  192. {
  193. return nullptr;
  194. }
  195. };
  196. template <class T, int I = 0, class... Tp>
  197. BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I == sizeof...(Tp) - 1, T>::type const *
  198. find_in_tuple(std::tuple<Tp...> const & t) noexcept
  199. {
  200. return get_dispatch<T>::get(&std::get<I>(t));
  201. }
  202. template<class T, int I = 0, class... Tp>
  203. BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I < sizeof...(Tp) - 1, T>::type const *
  204. find_in_tuple(std::tuple<Tp...> const & t) noexcept
  205. {
  206. if( T const * x = get_dispatch<T>::get(&std::get<I>(t)) )
  207. return x;
  208. else
  209. return find_in_tuple<T, I+1, Tp...>(t);
  210. }
  211. struct verbose_diagnostic_info_: verbose_diagnostic_info
  212. {
  213. template <class Tup>
  214. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, Tup const & tup, dynamic_allocator const * da ) noexcept:
  215. verbose_diagnostic_info(ei, tup, da)
  216. {
  217. }
  218. };
  219. template <>
  220. struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<dynamic_allocator>
  221. {
  222. template <class Tup>
  223. BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  224. {
  225. slot<dynamic_allocator> const * da = find_in_tuple<slot<dynamic_allocator>>(tup);
  226. return verbose_diagnostic_info_(ei, tup, da ? da->has_value() : nullptr );
  227. }
  228. };
  229. }
  230. #else
  231. class verbose_diagnostic_info: public diagnostic_info
  232. {
  233. protected:
  234. verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
  235. template <class Tup>
  236. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
  237. diagnostic_info(ei, tup)
  238. {
  239. }
  240. template <class CharT, class Traits>
  241. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
  242. {
  243. 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);
  244. }
  245. };
  246. namespace leaf_detail
  247. {
  248. struct verbose_diagnostic_info_: verbose_diagnostic_info
  249. {
  250. template <class Tup>
  251. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, Tup const & tup ) noexcept:
  252. verbose_diagnostic_info(ei, tup)
  253. {
  254. }
  255. };
  256. template <>
  257. struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
  258. {
  259. template <class Tup>
  260. BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
  261. {
  262. return verbose_diagnostic_info_(ei, tup);
  263. }
  264. };
  265. }
  266. #endif
  267. #else
  268. class verbose_diagnostic_info: public diagnostic_info
  269. {
  270. protected:
  271. verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
  272. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
  273. diagnostic_info(ei)
  274. {
  275. }
  276. template <class CharT, class Traits>
  277. friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
  278. {
  279. 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);
  280. }
  281. };
  282. namespace leaf_detail
  283. {
  284. struct verbose_diagnostic_info_: verbose_diagnostic_info
  285. {
  286. BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
  287. verbose_diagnostic_info(ei)
  288. {
  289. }
  290. };
  291. template <>
  292. struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
  293. {
  294. template <class Tup>
  295. BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const &, error_info const & ei ) noexcept
  296. {
  297. return verbose_diagnostic_info_(ei);
  298. }
  299. };
  300. }
  301. #endif
  302. ////////////////////////////////////////
  303. namespace leaf_detail
  304. {
  305. template <class T, class... List>
  306. struct type_index;
  307. template <class T, class... Cdr>
  308. struct type_index<T, T, Cdr...>
  309. {
  310. constexpr static int value = 0;
  311. };
  312. template <class T, class Car, class... Cdr>
  313. struct type_index<T, Car, Cdr...>
  314. {
  315. constexpr static int value = 1 + type_index<T,Cdr...>::value;
  316. };
  317. template <class T, class Tuple>
  318. struct tuple_type_index;
  319. template <class T, class... TupleTypes>
  320. struct tuple_type_index<T,std::tuple<TupleTypes...>>
  321. {
  322. constexpr static int value = type_index<T,TupleTypes...>::value;
  323. };
  324. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  325. template <class E, bool = std::is_class<E>::value>
  326. struct peek_exception;
  327. template <>
  328. struct peek_exception<std::exception const, true>
  329. {
  330. BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
  331. {
  332. return ei.exception();
  333. }
  334. };
  335. template <>
  336. struct peek_exception<std::exception, true>
  337. {
  338. BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
  339. {
  340. return ei.exception();
  341. }
  342. };
  343. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  344. template <>
  345. struct peek_exception<std::error_code const, true>
  346. {
  347. static std::error_code const * peek( error_info const & ei ) noexcept
  348. {
  349. auto const ex = ei.exception();
  350. if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
  351. return &se->code();
  352. else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
  353. return ec;
  354. else
  355. return nullptr;
  356. }
  357. };
  358. template <>
  359. struct peek_exception<std::error_code, true>
  360. {
  361. static std::error_code * peek( error_info const & ei ) noexcept
  362. {
  363. auto const ex = ei.exception();
  364. if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
  365. return const_cast<std::error_code *>(&se->code());
  366. else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
  367. return ec;
  368. else
  369. return nullptr;
  370. }
  371. };
  372. #endif
  373. template <class E>
  374. struct peek_exception<E, true>
  375. {
  376. static E * peek( error_info const & ei ) noexcept
  377. {
  378. return dynamic_cast<E *>(ei.exception());
  379. }
  380. };
  381. template <class E>
  382. struct peek_exception<E, false>
  383. {
  384. BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
  385. {
  386. return nullptr;
  387. }
  388. };
  389. #endif
  390. template <class E, bool = does_not_participate_in_context_deduction<E>::value>
  391. struct peek_tuple;
  392. template <class E>
  393. struct peek_tuple<E, true>
  394. {
  395. template <class SlotsTuple>
  396. BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const &, error_id const & ) noexcept
  397. {
  398. return nullptr;
  399. }
  400. template <class SlotsTuple>
  401. BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple &, error_id const & ) noexcept
  402. {
  403. return nullptr;
  404. }
  405. };
  406. template <class E>
  407. struct peek_tuple<E, false>
  408. {
  409. template <class SlotsTuple>
  410. BOOST_LEAF_CONSTEXPR static E const * peek( SlotsTuple const & tup, error_id const & err ) noexcept
  411. {
  412. return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
  413. }
  414. template <class SlotsTuple>
  415. BOOST_LEAF_CONSTEXPR static E * peek( SlotsTuple & tup, error_id const & err ) noexcept
  416. {
  417. return std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value());
  418. }
  419. };
  420. template <class E, class SlotsTuple>
  421. BOOST_LEAF_CONSTEXPR inline
  422. E const *
  423. peek( SlotsTuple const & tup, error_info const & ei ) noexcept
  424. {
  425. if( error_id err = ei.error() )
  426. {
  427. if( E const * e = peek_tuple<E>::peek(tup, err) )
  428. return e;
  429. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  430. else
  431. return peek_exception<E const>::peek(ei);
  432. #endif
  433. }
  434. return nullptr;
  435. }
  436. template <class E, class SlotsTuple>
  437. BOOST_LEAF_CONSTEXPR inline
  438. E *
  439. peek( SlotsTuple & tup, error_info const & ei ) noexcept
  440. {
  441. if( error_id err = ei.error() )
  442. {
  443. if( E * e = peek_tuple<E>::peek(tup, err) )
  444. return e;
  445. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  446. else
  447. return peek_exception<E>::peek(ei);
  448. #endif
  449. }
  450. return nullptr;
  451. }
  452. }
  453. ////////////////////////////////////////
  454. namespace leaf_detail
  455. {
  456. template <class A>
  457. template <class Tup>
  458. BOOST_LEAF_CONSTEXPR inline
  459. typename handler_argument_traits_defaults<A, false>::error_type const *
  460. handler_argument_traits_defaults<A, false>::
  461. check( Tup const & tup, error_info const & ei ) noexcept
  462. {
  463. return peek<typename std::decay<A>::type>(tup, ei);
  464. }
  465. template <class A>
  466. template <class Tup>
  467. BOOST_LEAF_CONSTEXPR inline
  468. typename handler_argument_traits_defaults<A, false>::error_type *
  469. handler_argument_traits_defaults<A, false>::
  470. check( Tup & tup, error_info const & ei ) noexcept
  471. {
  472. return peek<typename std::decay<A>::type>(tup, ei);
  473. }
  474. template <class Tup>
  475. BOOST_LEAF_CONSTEXPR inline
  476. std::exception const *
  477. handler_argument_traits<void>::
  478. check( Tup const &, error_info const & ei ) noexcept
  479. {
  480. return ei.exception();
  481. }
  482. template <class Tup, class... List>
  483. struct check_arguments;
  484. template <class Tup>
  485. struct check_arguments<Tup>
  486. {
  487. BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
  488. {
  489. return true;
  490. }
  491. };
  492. template <class Tup, class Car, class... Cdr>
  493. struct check_arguments<Tup, Car, Cdr...>
  494. {
  495. BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
  496. {
  497. return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
  498. }
  499. };
  500. }
  501. ////////////////////////////////////////
  502. namespace leaf_detail
  503. {
  504. template <class>
  505. struct handler_matches_any_error: std::false_type
  506. {
  507. };
  508. template <template<class...> class L>
  509. struct handler_matches_any_error<L<>>: std::true_type
  510. {
  511. };
  512. template <template<class...> class L, class Car, class... Cdr>
  513. struct handler_matches_any_error<L<Car, Cdr...>>
  514. {
  515. constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
  516. };
  517. }
  518. ////////////////////////////////////////
  519. namespace leaf_detail
  520. {
  521. template <class Tup, class... A>
  522. BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
  523. {
  524. return check_arguments<Tup, A...>::check(tup, ei);
  525. }
  526. template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
  527. struct handler_caller
  528. {
  529. template <class Tup, class... A>
  530. BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
  531. {
  532. return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
  533. }
  534. };
  535. template <template <class...> class Result, class... E, class F>
  536. struct handler_caller<Result<void, E...>, F, true, void>
  537. {
  538. using R = Result<void, E...>;
  539. template <class Tup, class... A>
  540. BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
  541. {
  542. std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
  543. return { };
  544. }
  545. };
  546. template <class T>
  547. struct is_tuple: std::false_type { };
  548. template <class... T>
  549. struct is_tuple<std::tuple<T...>>: std::true_type { };
  550. template <class... T>
  551. struct is_tuple<std::tuple<T...> &>: std::true_type { };
  552. template <class R, class Tup, class H>
  553. BOOST_LEAF_CONSTEXPR inline
  554. typename std::enable_if<!is_tuple<typename std::decay<H>::type>::value, R>::type
  555. handle_error_( Tup & tup, error_info const & ei, H && h )
  556. {
  557. static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
  558. return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
  559. }
  560. template <class R, class Tup, class Car, class... Cdr>
  561. BOOST_LEAF_CONSTEXPR inline
  562. typename std::enable_if<!is_tuple<typename std::decay<Car>::type>::value, R>::type
  563. handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
  564. {
  565. if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
  566. return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
  567. else
  568. return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
  569. }
  570. template <class R, class Tup, class HTup, size_t ... I>
  571. BOOST_LEAF_CONSTEXPR inline
  572. R
  573. handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
  574. {
  575. return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
  576. }
  577. template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
  578. BOOST_LEAF_CONSTEXPR inline
  579. R
  580. handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
  581. {
  582. return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
  583. }
  584. template <class R, class Tup, class H>
  585. BOOST_LEAF_CONSTEXPR inline
  586. typename std::enable_if<is_tuple<typename std::decay<H>::type>::value, R>::type
  587. handle_error_( Tup & tup, error_info const & ei, H && h )
  588. {
  589. return handle_error_tuple_<R>(
  590. tup,
  591. ei,
  592. leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
  593. std::forward<H>(h));
  594. }
  595. template <class R, class Tup, class Car, class... Cdr>
  596. BOOST_LEAF_CONSTEXPR inline
  597. typename std::enable_if<is_tuple<typename std::decay<Car>::type>::value, R>::type
  598. handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
  599. {
  600. return handle_error_tuple_<R>(
  601. tup,
  602. ei,
  603. leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
  604. std::forward<Car>(car),
  605. std::forward<Cdr>(cdr)...);
  606. }
  607. }
  608. ////////////////////////////////////////
  609. template <class... E>
  610. template <class R, class... H>
  611. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
  612. R
  613. context<E...>::
  614. handle_error( error_id id, H && ... h ) const
  615. {
  616. BOOST_LEAF_ASSERT(!is_active());
  617. return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
  618. }
  619. template <class... E>
  620. template <class R, class... H>
  621. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
  622. R
  623. context<E...>::
  624. handle_error( error_id id, H && ... h )
  625. {
  626. BOOST_LEAF_ASSERT(!is_active());
  627. return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
  628. }
  629. ////////////////////////////////////////
  630. namespace leaf_detail
  631. {
  632. template <class T>
  633. void unload_result( result<T> * r )
  634. {
  635. (void) r->unload();
  636. }
  637. inline void unload_result( void * )
  638. {
  639. }
  640. }
  641. ////////////////////////////////////////
  642. #ifdef BOOST_LEAF_NO_EXCEPTIONS
  643. template <class TryBlock, class... H>
  644. BOOST_LEAF_CONSTEXPR inline
  645. typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
  646. try_handle_all( TryBlock && try_block, H && ... h ) noexcept
  647. {
  648. 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");
  649. context_type_from_handlers<H...> ctx;
  650. auto active_context = activate_context(ctx);
  651. if( auto r = std::forward<TryBlock>(try_block)() )
  652. return std::move(r).value();
  653. else
  654. {
  655. leaf_detail::unload_result(&r);
  656. error_id id = r.error();
  657. ctx.deactivate();
  658. using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
  659. return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
  660. }
  661. }
  662. template <class TryBlock, class... H>
  663. BOOST_LEAF_ATTRIBUTE_NODISCARD BOOST_LEAF_CONSTEXPR inline
  664. typename std::decay<decltype(std::declval<TryBlock>()())>::type
  665. try_handle_some( TryBlock && try_block, H && ... h ) noexcept
  666. {
  667. 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");
  668. context_type_from_handlers<H...> ctx;
  669. auto active_context = activate_context(ctx);
  670. if( auto r = std::forward<TryBlock>(try_block)() )
  671. return r;
  672. else
  673. {
  674. leaf_detail::unload_result(&r);
  675. error_id id = r.error();
  676. ctx.deactivate();
  677. using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
  678. auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
  679. if( !rr )
  680. ctx.unload(rr.error());
  681. return rr;
  682. }
  683. }
  684. template <class TryBlock, class... H>
  685. BOOST_LEAF_CONSTEXPR inline
  686. decltype(std::declval<TryBlock>()())
  687. try_catch( TryBlock && try_block, H && ... ) noexcept
  688. {
  689. static_assert(sizeof(context_type_from_handlers<H...>) > 0,
  690. "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.");
  691. return std::forward<TryBlock>(try_block)();
  692. }
  693. #else
  694. namespace leaf_detail
  695. {
  696. template <class Ctx, class TryBlock, class... H>
  697. decltype(std::declval<TryBlock>()())
  698. try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
  699. {
  700. using namespace leaf_detail;
  701. BOOST_LEAF_ASSERT(ctx.is_active());
  702. using R = decltype(std::declval<TryBlock>()());
  703. try
  704. {
  705. auto r = std::forward<TryBlock>(try_block)();
  706. unload_result(&r);
  707. return std::move(r);
  708. }
  709. catch( std::exception & ex )
  710. {
  711. ctx.deactivate();
  712. error_info e(&ex);
  713. return handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
  714. [&]() -> R
  715. {
  716. ctx.unload(e.error());
  717. throw;
  718. } );
  719. }
  720. catch(...)
  721. {
  722. ctx.deactivate();
  723. error_info e(nullptr);
  724. return handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
  725. [&]() -> R
  726. {
  727. ctx.unload(e.error());
  728. throw;
  729. } );
  730. }
  731. }
  732. }
  733. template <class TryBlock, class... H>
  734. inline
  735. typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
  736. try_handle_all( TryBlock && try_block, H && ... h )
  737. {
  738. 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");
  739. context_type_from_handlers<H...> ctx;
  740. auto active_context = activate_context(ctx);
  741. if( auto r = leaf_detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
  742. return std::move(r).value();
  743. else
  744. {
  745. BOOST_LEAF_ASSERT(ctx.is_active());
  746. leaf_detail::unload_result(&r);
  747. error_id id = r.error();
  748. ctx.deactivate();
  749. using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
  750. return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
  751. }
  752. }
  753. template <class TryBlock, class... H>
  754. BOOST_LEAF_ATTRIBUTE_NODISCARD inline
  755. typename std::decay<decltype(std::declval<TryBlock>()())>::type
  756. try_handle_some( TryBlock && try_block, H && ... h )
  757. {
  758. 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");
  759. context_type_from_handlers<H...> ctx;
  760. auto active_context = activate_context(ctx);
  761. if( auto r = leaf_detail::try_catch_(ctx, std::forward<TryBlock>(try_block), std::forward<H>(h)...) )
  762. return r;
  763. else if( ctx.is_active() )
  764. {
  765. leaf_detail::unload_result(&r);
  766. error_id id = r.error();
  767. ctx.deactivate();
  768. using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
  769. auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...,
  770. [&r]()->R
  771. {
  772. return std::move(r);
  773. });
  774. if( !rr )
  775. ctx.unload(rr.error());
  776. return rr;
  777. }
  778. else
  779. {
  780. ctx.unload(r.error());
  781. return r;
  782. }
  783. }
  784. template <class TryBlock, class... H>
  785. inline
  786. decltype(std::declval<TryBlock>()())
  787. try_catch( TryBlock && try_block, H && ... h )
  788. {
  789. context_type_from_handlers<H...> ctx;
  790. auto active_context = activate_context(ctx);
  791. using R = decltype(std::declval<TryBlock>()());
  792. try
  793. {
  794. return std::forward<TryBlock>(try_block)();
  795. }
  796. catch( std::exception & ex )
  797. {
  798. ctx.deactivate();
  799. error_info e(&ex);
  800. return leaf_detail::handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
  801. [&]() -> R
  802. {
  803. ctx.unload(e.error());
  804. throw;
  805. } );
  806. }
  807. catch(...)
  808. {
  809. ctx.deactivate();
  810. error_info e(nullptr);
  811. return leaf_detail::handle_error_<R>(ctx.tup(), e, std::forward<H>(h)...,
  812. [&]() -> R
  813. {
  814. ctx.unload(e.error());
  815. throw;
  816. } );
  817. }
  818. }
  819. #endif
  820. #if BOOST_LEAF_CFG_CAPTURE
  821. namespace leaf_detail
  822. {
  823. template <class LeafResult>
  824. struct try_capture_all_dispatch_non_void
  825. {
  826. using leaf_result = LeafResult;
  827. template <class TryBlock>
  828. inline
  829. static
  830. leaf_result
  831. try_capture_all_( TryBlock && try_block ) noexcept
  832. {
  833. leaf_detail::slot<leaf_detail::dynamic_allocator> sl;
  834. sl.activate();
  835. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  836. try
  837. #endif
  838. {
  839. if( leaf_result r = std::forward<TryBlock>(try_block)() )
  840. {
  841. sl.deactivate();
  842. return r;
  843. }
  844. else
  845. {
  846. sl.deactivate();
  847. int const err_id = error_id(r.error()).value();
  848. return leaf_result(sl.value(err_id).template extract_capture_list<leaf_result>(err_id));
  849. }
  850. }
  851. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  852. catch( std::exception & ex )
  853. {
  854. sl.deactivate();
  855. int const err_id = error_info(&ex).error().value();
  856. return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
  857. }
  858. catch(...)
  859. {
  860. sl.deactivate();
  861. int const err_id = error_info(nullptr).error().value();
  862. return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
  863. }
  864. #endif
  865. }
  866. };
  867. template <class R, bool IsVoid = std::is_same<void, R>::value, bool IsResultType = is_result_type<R>::value>
  868. struct try_capture_all_dispatch;
  869. template <class R>
  870. struct try_capture_all_dispatch<R, false, true>:
  871. try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::decay<decltype(std::declval<R>().value())>::type>>
  872. {
  873. };
  874. template <class R>
  875. struct try_capture_all_dispatch<R, false, false>:
  876. try_capture_all_dispatch_non_void<::boost::leaf::result<typename std::remove_reference<R>::type>>
  877. {
  878. };
  879. template <class R>
  880. struct try_capture_all_dispatch<R, true, false>
  881. {
  882. using leaf_result = ::boost::leaf::result<R>;
  883. template <class TryBlock>
  884. inline
  885. static
  886. leaf_result
  887. try_capture_all_( TryBlock && try_block ) noexcept
  888. {
  889. leaf_detail::slot<leaf_detail::dynamic_allocator> sl;
  890. sl.activate();
  891. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  892. try
  893. #endif
  894. {
  895. std::forward<TryBlock>(try_block)();
  896. return {};
  897. }
  898. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  899. catch( std::exception & ex )
  900. {
  901. sl.deactivate();
  902. int const err_id = error_info(&ex).error().value();
  903. return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
  904. }
  905. catch(...)
  906. {
  907. sl.deactivate();
  908. int const err_id = error_info(nullptr).error().value();
  909. return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
  910. }
  911. #endif
  912. }
  913. };
  914. }
  915. template <class TryBlock>
  916. inline
  917. typename leaf_detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::leaf_result
  918. try_capture_all( TryBlock && try_block ) noexcept
  919. {
  920. return leaf_detail::try_capture_all_dispatch<decltype(std::declval<TryBlock>()())>::try_capture_all_(std::forward<TryBlock>(try_block));
  921. }
  922. #endif
  923. } }
  924. // Boost Exception Integration
  925. namespace boost { class exception; }
  926. namespace boost { template <class Tag,class T> class error_info; }
  927. namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
  928. namespace boost { namespace leaf {
  929. namespace leaf_detail
  930. {
  931. template <class T>
  932. struct match_enum_type;
  933. template <class Tag, class T>
  934. struct match_enum_type<boost::error_info<Tag, T>>
  935. {
  936. using type = T;
  937. };
  938. template <class Ex>
  939. BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
  940. {
  941. return dynamic_cast<Ex *>(ei.exception());
  942. }
  943. template <class, class T>
  944. struct dependent_type { using type = T; };
  945. template <class Dep, class T>
  946. using dependent_type_t = typename dependent_type<Dep, T>::type;
  947. template <class Tag, class T>
  948. struct handler_argument_traits<boost::error_info<Tag, T>>
  949. {
  950. using error_type = void;
  951. constexpr static bool always_available = false;
  952. template <class Tup>
  953. BOOST_LEAF_CONSTEXPR static T * check( Tup &, error_info const & ei ) noexcept
  954. {
  955. using boost_exception = dependent_type_t<T, boost::exception>;
  956. if( auto * be = get_exception<boost_exception>(ei) )
  957. return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
  958. else
  959. return nullptr;
  960. }
  961. template <class Tup>
  962. BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
  963. {
  964. return boost::error_info<Tag, T>(*check(tup, ei));
  965. }
  966. };
  967. 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>> { };
  968. 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>> { };
  969. 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>> { };
  970. 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>> { };
  971. }
  972. } }
  973. #endif