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