]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/leaf.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / leaf.hpp
1 #ifndef BOOST_LEAF_HPP_INCLUDED
2 #define BOOST_LEAF_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 // >>> #include <boost/leaf/capture.hpp>
10 #line 1 "boost/leaf/capture.hpp"
11 #ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED
12 #define BOOST_LEAF_CAPTURE_HPP_INCLUDED
13
14 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
15
16 // Distributed under the Boost Software License, Version 1.0. (See accompanying
17 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
18
19 #ifndef BOOST_LEAF_ENABLE_WARNINGS
20 # if defined(__clang__)
21 # pragma clang system_header
22 # elif (__GNUC__*100+__GNUC_MINOR__>301)
23 # pragma GCC system_header
24 # elif defined(_MSC_VER)
25 # pragma warning(push,1)
26 # endif
27 #endif
28
29 // >>> #include <boost/leaf/exception.hpp>
30 #line 1 "boost/leaf/exception.hpp"
31 #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
32 #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED
33
34 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
35
36 // Distributed under the Boost Software License, Version 1.0. (See accompanying
37 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
38
39 #ifndef BOOST_LEAF_ENABLE_WARNINGS
40 # if defined(__clang__)
41 # pragma clang system_header
42 # elif (__GNUC__*100+__GNUC_MINOR__>301)
43 # pragma GCC system_header
44 # elif defined(_MSC_VER)
45 # pragma warning(push,1)
46 # endif
47 #endif
48
49 // >>> #include <boost/leaf/error.hpp>
50 #line 1 "boost/leaf/error.hpp"
51 #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED
52 #define BOOST_LEAF_ERROR_HPP_INCLUDED
53
54 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
55
56 // Distributed under the Boost Software License, Version 1.0. (See accompanying
57 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
58
59 #ifndef BOOST_LEAF_ENABLE_WARNINGS
60 # if defined(__clang__)
61 # pragma clang system_header
62 # elif (__GNUC__*100+__GNUC_MINOR__>301)
63 # pragma GCC system_header
64 # elif defined(_MSC_VER)
65 # pragma warning(push,1)
66 # endif
67 #endif
68
69 // >>> #include <boost/leaf/detail/function_traits.hpp>
70 #line 1 "boost/leaf/detail/function_traits.hpp"
71 #ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
72 #define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED
73
74 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
75
76 // Distributed under the Boost Software License, Version 1.0. (See accompanying
77 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
78
79 #ifndef BOOST_LEAF_ENABLE_WARNINGS
80 # if defined(__clang__)
81 # pragma clang system_header
82 # elif (__GNUC__*100+__GNUC_MINOR__>301)
83 # pragma GCC system_header
84 # elif defined(_MSC_VER)
85 # pragma warning(push,1)
86 # endif
87 #endif
88
89 // >>> #include <boost/leaf/detail/mp11.hpp>
90 #line 1 "boost/leaf/detail/mp11.hpp"
91 #ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED
92 #define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED
93
94 // Copyright 2015-2017 Peter Dimov.
95 // Copyright 2019 Emil Dotchevski.
96 //
97 // Distributed under the Boost Software License, Version 1.0.
98 //
99 // See accompanying file LICENSE_1_0.txt or copy at
100 // http://www.boost.org/LICENSE_1_0.txt
101
102 #include <type_traits>
103 #include <cstddef>
104
105 namespace boost { namespace leaf { namespace leaf_detail_mp11 {
106
107 // mp_list<T...>
108 template<class... T> struct mp_list
109 {
110 };
111
112 // mp_identity
113 template<class T> struct mp_identity
114 {
115 using type = T;
116 };
117
118 // mp_inherit
119 template<class... T> struct mp_inherit: T... {};
120
121 // mp_if, mp_if_c
122 namespace detail
123 {
124
125 template<bool C, class T, class... E> struct mp_if_c_impl
126 {
127 };
128
129 template<class T, class... E> struct mp_if_c_impl<true, T, E...>
130 {
131 using type = T;
132 };
133
134 template<class T, class E> struct mp_if_c_impl<false, T, E>
135 {
136 using type = E;
137 };
138
139 } // namespace detail
140
141 template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
142 template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
143
144 // mp_bool
145 template<bool B> using mp_bool = std::integral_constant<bool, B>;
146
147 using mp_true = mp_bool<true>;
148 using mp_false = mp_bool<false>;
149
150 // mp_to_bool
151 template<class T> using mp_to_bool = mp_bool<static_cast<bool>( T::value )>;
152
153 // mp_not<T>
154 template<class T> using mp_not = mp_bool< !T::value >;
155
156 // mp_int
157 template<int I> using mp_int = std::integral_constant<int, I>;
158
159 // mp_size_t
160 template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
161
162 // mp_set_contains<S, V>
163 namespace detail
164 {
165
166 template<class S, class V> struct mp_set_contains_impl;
167
168 template<template<class...> class L, class... T, class V> struct mp_set_contains_impl<L<T...>, V>
169 {
170 using type = mp_to_bool<std::is_base_of<mp_identity<V>, mp_inherit<mp_identity<T>...> > >;
171 };
172
173 } // namespace detail
174
175 template<class S, class V> using mp_set_contains = typename detail::mp_set_contains_impl<S, V>::type;
176
177 // mp_set_push_back<S, T...>
178 namespace detail
179 {
180
181 template<class S, class... T> struct mp_set_push_back_impl;
182
183 template<template<class...> class L, class... U> struct mp_set_push_back_impl<L<U...>>
184 {
185 using type = L<U...>;
186 };
187
188 template<template<class...> class L, class... U, class T1, class... T> struct mp_set_push_back_impl<L<U...>, T1, T...>
189 {
190 using S = mp_if<mp_set_contains<L<U...>, T1>, L<U...>, L<U..., T1>>;
191 using type = typename mp_set_push_back_impl<S, T...>::type;
192 };
193
194 } // namespace detail
195
196 template<class S, class... T> using mp_set_push_back = typename detail::mp_set_push_back_impl<S, T...>::type;
197
198 // mp_unique<L>
199 namespace detail
200 {
201
202 template<class L> struct mp_unique_impl;
203
204 template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>>
205 {
206 using type = mp_set_push_back<L<>, T...>;
207 };
208
209 } // namespace detail
210
211 template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type;
212
213 // mp_append<L...>
214
215 namespace detail
216 {
217
218 template<class... L> struct mp_append_impl;
219
220 template<> struct mp_append_impl<>
221 {
222 using type = mp_list<>;
223 };
224
225 template<template<class...> class L, class... T> struct mp_append_impl<L<T...>>
226 {
227 using type = L<T...>;
228 };
229
230 template<template<class...> class L1, class... T1, template<class...> class L2, class... T2, class... Lr> struct mp_append_impl<L1<T1...>, L2<T2...>, Lr...>
231 {
232 using type = typename mp_append_impl<L1<T1..., T2...>, Lr...>::type;
233 };
234
235 }
236
237 template<class... L> using mp_append = typename detail::mp_append_impl<L...>::type;
238
239 // mp_front<L>
240 namespace detail
241 {
242
243 template<class L> struct mp_front_impl
244 {
245 // An error "no type named 'type'" here means that the argument to mp_front
246 // is either not a list, or is an empty list
247 };
248
249 template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>>
250 {
251 using type = T1;
252 };
253
254 } // namespace detail
255
256 template<class L> using mp_front = typename detail::mp_front_impl<L>::type;
257
258 // mp_pop_front<L>
259 namespace detail
260 {
261
262 template<class L> struct mp_pop_front_impl
263 {
264 // An error "no type named 'type'" here means that the argument to mp_pop_front
265 // is either not a list, or is an empty list
266 };
267
268 template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>>
269 {
270 using type = L<T...>;
271 };
272
273 } // namespace detail
274
275 template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
276
277 // mp_first<L>
278 template<class L> using mp_first = mp_front<L>;
279
280 // mp_rest<L>
281 template<class L> using mp_rest = mp_pop_front<L>;
282
283 // mp_remove_if<L, P>
284 namespace detail
285 {
286
287 template<class L, template<class...> class P> struct mp_remove_if_impl;
288
289 template<template<class...> class L, class... T, template<class...> class P> struct mp_remove_if_impl<L<T...>, P>
290 {
291 template<class U> using _f = mp_if<P<U>, mp_list<>, mp_list<U>>;
292 using type = mp_append<L<>, _f<T>...>;
293 };
294
295 } // namespace detail
296
297 template<class L, template<class...> class P> using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
298
299 // integer_sequence
300 template<class T, T... I> struct integer_sequence
301 {
302 };
303
304 // detail::make_integer_sequence_impl
305 namespace detail
306 {
307
308 // iseq_if_c
309 template<bool C, class T, class E> struct iseq_if_c_impl;
310
311 template<class T, class E> struct iseq_if_c_impl<true, T, E>
312 {
313 using type = T;
314 };
315
316 template<class T, class E> struct iseq_if_c_impl<false, T, E>
317 {
318 using type = E;
319 };
320
321 template<bool C, class T, class E> using iseq_if_c = typename iseq_if_c_impl<C, T, E>::type;
322
323 // iseq_identity
324 template<class T> struct iseq_identity
325 {
326 using type = T;
327 };
328
329 template<class S1, class S2> struct append_integer_sequence;
330
331 template<class T, T... I, T... J> struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
332 {
333 using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >;
334 };
335
336 template<class T, T N> struct make_integer_sequence_impl;
337
338 template<class T, T N> struct make_integer_sequence_impl_
339 {
340 private:
341
342 static_assert( N >= 0, "make_integer_sequence<T, N>: N must not be negative" );
343
344 static T const M = N / 2;
345 static T const R = N % 2;
346
347 using S1 = typename make_integer_sequence_impl<T, M>::type;
348 using S2 = typename append_integer_sequence<S1, S1>::type;
349 using S3 = typename make_integer_sequence_impl<T, R>::type;
350 using S4 = typename append_integer_sequence<S2, S3>::type;
351
352 public:
353
354 using type = S4;
355 };
356
357 template<class T, T N> struct make_integer_sequence_impl: iseq_if_c<N == 0, iseq_identity<integer_sequence<T>>, iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, make_integer_sequence_impl_<T, N> > >
358 {
359 };
360
361 } // namespace detail
362
363 // make_integer_sequence
364 template<class T, T N> using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
365
366 // index_sequence
367 template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
368
369 // make_index_sequence
370 template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>;
371
372 // index_sequence_for
373 template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
374
375 // implementation by Bruno Dutra (by the name is_evaluable)
376 namespace detail
377 {
378
379 template<template<class...> class F, class... T> struct mp_valid_impl
380 {
381 template<template<class...> class G, class = G<T...>> static mp_true check(int);
382 template<template<class...> class> static mp_false check(...);
383
384 using type = decltype(check<F>(0));
385 };
386
387 } // namespace detail
388
389 template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
390
391 } } }
392
393 #endif
394 // <<< #include <boost/leaf/detail/mp11.hpp>
395 #line 20 "boost/leaf/detail/function_traits.hpp"
396 #include <tuple>
397
398 namespace boost { namespace leaf {
399
400 namespace leaf_detail
401 {
402 template<class...>
403 struct gcc49_workaround //Thanks Glen Fernandes
404 {
405 using type = void;
406 };
407
408 template<class... T>
409 using void_t = typename gcc49_workaround<T...>::type;
410
411 template<class F,class V=void>
412 struct function_traits
413 {
414 constexpr static int arity = -1;
415 };
416
417 template<class F>
418 struct function_traits<F, void_t<decltype(&F::operator())>>
419 {
420 private:
421
422 using tr = function_traits<decltype(&F::operator())>;
423
424 public:
425
426 using return_type = typename tr::return_type;
427 static constexpr int arity = tr::arity - 1;
428
429 using mp_args = typename leaf_detail_mp11::mp_rest<typename tr::mp_args>;
430
431 template <int I>
432 struct arg:
433 tr::template arg<I+1>
434 {
435 };
436 };
437
438 template<class R, class... A>
439 struct function_traits<R(A...)>
440 {
441 using return_type = R;
442 static constexpr int arity = sizeof...(A);
443
444 using mp_args = leaf_detail_mp11::mp_list<A...>;
445
446 template <int I>
447 struct arg
448 {
449 static_assert(I < arity, "I out of range");
450 using type = typename std::tuple_element<I,std::tuple<A...>>::type;
451 };
452 };
453
454 template<class F> struct function_traits<F&> : function_traits<F> { };
455 template<class F> struct function_traits<F&&> : function_traits<F> { };
456 template<class R, class... A> struct function_traits<R(*)(A...)> : function_traits<R(A...)> { };
457 template<class R, class... A> struct function_traits<R(* &)(A...)> : function_traits<R(A...)> { };
458 template<class R, class... A> struct function_traits<R(* const &)(A...)> : function_traits<R(A...)> { };
459 template<class C, class R, class... A> struct function_traits<R(C::*)(A...)> : function_traits<R(C&,A...)> { };
460 template<class C, class R, class... A> struct function_traits<R(C::*)(A...) const> : function_traits<R(C const &,A...)> { };
461 template<class C, class R> struct function_traits<R(C::*)> : function_traits<R(C&)> { };
462
463 template <class F>
464 using fn_return_type = typename function_traits<F>::return_type;
465
466 template <class F, int I>
467 using fn_arg_type = typename function_traits<F>::template arg<I>::type;
468
469 template <class F>
470 using fn_mp_args = typename function_traits<F>::mp_args;
471
472 }
473
474 } }
475
476 #endif
477 // <<< #include <boost/leaf/detail/function_traits.hpp>
478 #line 20 "boost/leaf/error.hpp"
479 // >>> #include <boost/leaf/detail/print.hpp>
480 #line 1 "boost/leaf/detail/print.hpp"
481 #ifndef BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED
482 #define BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED
483
484 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
485
486 // Distributed under the Boost Software License, Version 1.0. (See accompanying
487 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
488
489 #ifndef BOOST_LEAF_ENABLE_WARNINGS
490 # if defined(__clang__)
491 # pragma clang system_header
492 # elif (__GNUC__*100+__GNUC_MINOR__>301)
493 # pragma GCC system_header
494 # elif defined(_MSC_VER)
495 # pragma warning(push,1)
496 # endif
497 #endif
498
499 // >>> #include <boost/leaf/detail/optional.hpp>
500 #line 1 "boost/leaf/detail/optional.hpp"
501 #ifndef BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED
502 #define BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED
503
504 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
505
506 // Distributed under the Boost Software License, Version 1.0. (See accompanying
507 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
508
509 #ifndef BOOST_LEAF_ENABLE_WARNINGS
510 # if defined(__clang__)
511 # pragma clang system_header
512 # elif (__GNUC__*100+__GNUC_MINOR__>301)
513 # pragma GCC system_header
514 # elif defined(_MSC_VER)
515 # pragma warning(push,1)
516 # endif
517 #endif
518
519 // >>> #include <boost/leaf/detail/config.hpp>
520 #line 1 "boost/leaf/detail/config.hpp"
521 #ifndef BOOST_LEAF_CONFIG_HPP_INCLUDED
522 #define BOOST_LEAF_CONFIG_HPP_INCLUDED
523
524 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
525
526 // Distributed under the Boost Software License, Version 1.0. (See accompanying
527 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
528
529 // The following is based on Boost Config.
530
531 // (C) Copyright John Maddock 2001 - 2003.
532 // (C) Copyright Martin Wille 2003.
533 // (C) Copyright Guillaume Melquiond 2003.
534
535 #ifndef BOOST_LEAF_ENABLE_WARNINGS
536 # if defined(__clang__)
537 # pragma clang system_header
538 # elif (__GNUC__*100+__GNUC_MINOR__>301)
539 # pragma GCC system_header
540 # elif defined(_MSC_VER)
541 # pragma warning(push,1)
542 # endif
543 #endif
544
545 ////////////////////////////////////////
546
547 // Configure BOOST_LEAF_NO_EXCEPTIONS, unless already #defined
548 #ifndef BOOST_LEAF_NO_EXCEPTIONS
549
550 # if defined(__clang__) && !defined(__ibmxl__)
551 // Clang C++ emulates GCC, so it has to appear early.
552
553 # if !__has_feature(cxx_exceptions)
554 # define BOOST_LEAF_NO_EXCEPTIONS
555 # endif
556
557 # elif defined(__DMC__)
558 // Digital Mars C++
559
560 # if !defined(_CPPUNWIND)
561 # define BOOST_LEAF_NO_EXCEPTIONS
562 # endif
563
564 # elif defined(__GNUC__) && !defined(__ibmxl__)
565 // GNU C++:
566
567 # if !defined(__EXCEPTIONS)
568 # define BOOST_LEAF_NO_EXCEPTIONS
569 # endif
570
571 # elif defined(__KCC)
572 // Kai C++
573
574 # if !defined(_EXCEPTIONS)
575 # define BOOST_LEAF_NO_EXCEPTIONS
576 # endif
577
578 # elif defined(__CODEGEARC__)
579 // CodeGear - must be checked for before Borland
580
581 # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS)
582 # define BOOST_LEAF_NO_EXCEPTIONS
583 # endif
584
585 # elif defined(__BORLANDC__)
586 // Borland
587
588 # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS)
589 # define BOOST_LEAF_NO_EXCEPTIONS
590 # endif
591
592 # elif defined(__MWERKS__)
593 // Metrowerks CodeWarrior
594
595 # if !__option(exceptions)
596 # define BOOST_LEAF_NO_EXCEPTIONS
597 # endif
598
599 # elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__)
600 // IBM z/OS XL C/C++
601
602 # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS)
603 # define BOOST_LEAF_NO_EXCEPTIONS
604 # endif
605
606 # elif defined(__ibmxl__)
607 // IBM XL C/C++ for Linux (Little Endian)
608
609 # if !__has_feature(cxx_exceptions)
610 # define BOOST_LEAF_NO_EXCEPTIONS
611 # endif
612
613 # elif defined(_MSC_VER)
614 // Microsoft Visual C++
615 //
616 // Must remain the last #elif since some other vendors (Metrowerks, for
617 // example) also #define _MSC_VER
618
619 # if !defined(_CPPUNWIND)
620 # define BOOST_LEAF_NO_EXCEPTIONS
621 # endif
622 # endif
623
624 #endif
625
626 #ifdef BOOST_NORETURN
627 # define BOOST_LEAF_NORETURN BOOST_NORETURN
628 #else
629 # if defined(_MSC_VER)
630 # define BOOST_LEAF_NORETURN __declspec(noreturn)
631 # elif defined(__GNUC__)
632 # define BOOST_LEAF_NORETURN __attribute__ ((__noreturn__))
633 # elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130)
634 # if __has_attribute(noreturn)
635 # define BOOST_LEAF_NORETURN [[noreturn]]
636 # endif
637 # elif defined(__has_cpp_attribute)
638 # if __has_cpp_attribute(noreturn)
639 # define BOOST_LEAF_NORETURN [[noreturn]]
640 # endif
641 # endif
642 #endif
643 #if !defined(BOOST_LEAF_NORETURN)
644 # define BOOST_LEAF_NORETURN
645 #endif
646
647 ////////////////////////////////////////
648
649 #ifndef BOOST_LEAF_DIAGNOSTICS
650 # define BOOST_LEAF_DIAGNOSTICS 1
651 #endif
652
653 #if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1
654 # error BOOST_LEAF_DIAGNOSTICS must be 0 or 1.
655 #endif
656
657 ////////////////////////////////////////
658
659 #ifdef _MSC_VER
660 # define BOOST_LEAF_ALWAYS_INLINE __forceinline
661 #else
662 # define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline
663 #endif
664
665 ////////////////////////////////////////
666
667 #ifndef BOOST_LEAF_NODISCARD
668 # if __cplusplus >= 201703L
669 # define BOOST_LEAF_NODISCARD [[nodiscard]]
670 # else
671 # define BOOST_LEAF_NODISCARD
672 # endif
673 #endif
674
675 ////////////////////////////////////////
676
677 #ifndef BOOST_LEAF_CONSTEXPR
678 # if __cplusplus > 201402L
679 # define BOOST_LEAF_CONSTEXPR constexpr
680 # else
681 # define BOOST_LEAF_CONSTEXPR
682 # endif
683 #endif
684
685 ////////////////////////////////////////
686
687 #ifndef BOOST_LEAF_ASSERT
688 # ifdef BOOST_ASSERT
689 # define BOOST_LEAF_ASSERT BOOST_ASSERT
690 # else
691 # include <cassert>
692 # define BOOST_LEAF_ASSERT assert
693 # endif
694 #endif
695
696 ////////////////////////////////////////
697
698 #ifndef BOOST_LEAF_NO_EXCEPTIONS
699 # include <exception>
700 # if (defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
701 # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1
702 # else
703 # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0
704 # endif
705 #endif
706
707 #endif
708 // <<< #include <boost/leaf/detail/config.hpp>
709 #line 20 "boost/leaf/detail/optional.hpp"
710 #include <utility>
711 #include <new>
712
713 namespace boost { namespace leaf {
714
715 namespace leaf_detail
716 {
717 template <class T>
718 class optional
719 {
720 int key_;
721 union { T value_; };
722
723 public:
724
725 typedef T value_type;
726
727 BOOST_LEAF_CONSTEXPR optional() noexcept:
728 key_(0)
729 {
730 }
731
732 BOOST_LEAF_CONSTEXPR optional( optional const & x ):
733 key_(x.key_)
734 {
735 if( x.key_ )
736 (void) new (&value_) T( x.value_ );
737 }
738
739 BOOST_LEAF_CONSTEXPR optional( optional && x ) noexcept:
740 key_(x.key_)
741 {
742 if( x.key_ )
743 {
744 (void) new (&value_) T( std::move(x.value_) );
745 x.reset();
746 }
747 }
748
749 BOOST_LEAF_CONSTEXPR optional( int key, T const & v ):
750 key_(key),
751 value_(v)
752 {
753 BOOST_LEAF_ASSERT(!empty());
754 }
755
756 BOOST_LEAF_CONSTEXPR optional( int key, T && v ) noexcept:
757 key_(key),
758 value_(std::move(v))
759 {
760 BOOST_LEAF_ASSERT(!empty());
761 }
762
763 BOOST_LEAF_CONSTEXPR optional & operator=( optional const & x )
764 {
765 reset();
766 if( int key = x.key() )
767 {
768 put(key, x.value_);
769 key_ = key;
770 }
771 return *this;
772 }
773
774 BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept
775 {
776 reset();
777 if( int key = x.key() )
778 {
779 put(key, std::move(x.value_));
780 x.reset();
781 }
782 return *this;
783 }
784
785 ~optional() noexcept
786 {
787 reset();
788 }
789
790 BOOST_LEAF_CONSTEXPR bool empty() const noexcept
791 {
792 return key_==0;
793 }
794
795 BOOST_LEAF_CONSTEXPR int key() const noexcept
796 {
797 return key_;
798 }
799
800 BOOST_LEAF_CONSTEXPR void reset() noexcept
801 {
802 if( key_ )
803 {
804 value_.~T();
805 key_=0;
806 }
807 }
808
809 BOOST_LEAF_CONSTEXPR T & put( int key, T const & v )
810 {
811 BOOST_LEAF_ASSERT(key);
812 reset();
813 (void) new(&value_) T(v);
814 key_=key;
815 return value_;
816 }
817
818 BOOST_LEAF_CONSTEXPR T & put( int key, T && v ) noexcept
819 {
820 BOOST_LEAF_ASSERT(key);
821 reset();
822 (void) new(&value_) T(std::move(v));
823 key_=key;
824 return value_;
825 }
826
827 BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept
828 {
829 BOOST_LEAF_ASSERT(key);
830 return key_==key ? &value_ : 0;
831 }
832
833 BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept
834 {
835 BOOST_LEAF_ASSERT(key);
836 return key_==key ? &value_ : 0;
837 }
838
839 BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept
840 {
841 BOOST_LEAF_ASSERT(has_value(key) != 0);
842 return value_;
843 }
844
845 BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept
846 {
847 BOOST_LEAF_ASSERT(has_value(key) != 0);
848 return value_;
849 }
850
851 BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept
852 {
853 BOOST_LEAF_ASSERT(has_value(key) != 0);
854 return value_;
855 }
856
857 BOOST_LEAF_CONSTEXPR T value(int key) && noexcept
858 {
859 BOOST_LEAF_ASSERT(has_value(key) != 0);
860 T tmp(std::move(value_));
861 reset();
862 return tmp;
863 }
864 };
865
866 }
867
868 } }
869
870 #endif
871 // <<< #include <boost/leaf/detail/optional.hpp>
872 #line 20 "boost/leaf/detail/print.hpp"
873 #include <iosfwd>
874 #include <cstring>
875
876 namespace boost { namespace leaf {
877
878 namespace leaf_detail
879 {
880 template <int N>
881 BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] )
882 {
883 return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t;
884 }
885 }
886
887 template <class Name>
888 inline char const * type()
889 {
890 using leaf_detail::check_prefix;
891 char const * t =
892 #ifdef __FUNCSIG__
893 __FUNCSIG__;
894 #else
895 __PRETTY_FUNCTION__;
896 #endif
897 #if defined(__clang__)
898 BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32);
899 return t+32;
900 #elif defined(__GNUC__)
901 BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32);
902 return t+32;
903 #else
904 char const * clang_style = check_prefix(t,"const char *boost::leaf::type() ");
905 if( clang_style!=t )
906 return clang_style;
907 char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() ");
908 if( gcc_style!=t )
909 return gcc_style;
910 #endif
911 return t;
912 }
913
914 namespace leaf_detail
915 {
916 template <class T, class E = void>
917 struct is_printable: std::false_type
918 {
919 };
920
921 template <class T>
922 struct is_printable<T, decltype(std::declval<std::ostream&>()<<std::declval<T const &>(), void())>: std::true_type
923 {
924 };
925
926 ////////////////////////////////////////
927
928 template <class T, class E = void>
929 struct has_printable_member_value: std::false_type
930 {
931 };
932
933 template <class T>
934 struct has_printable_member_value<T, decltype(std::declval<std::ostream&>()<<std::declval<T const &>().value, void())>: std::true_type
935 {
936 };
937
938 ////////////////////////////////////////
939
940 template <class Wrapper, bool WrapperPrintable=is_printable<Wrapper>::value, bool ValuePrintable=has_printable_member_value<Wrapper>::value>
941 struct diagnostic;
942
943 template <class Wrapper, bool ValuePrintable>
944 struct diagnostic<Wrapper, true, ValuePrintable>
945 {
946 static constexpr bool is_invisible = false;
947 static void print( std::ostream & os, Wrapper const & x )
948 {
949 os << x;
950 }
951 };
952
953 template <class Wrapper>
954 struct diagnostic<Wrapper, false, true>
955 {
956 static constexpr bool is_invisible = false;
957 static void print( std::ostream & os, Wrapper const & x )
958 {
959 os << type<Wrapper>() << ": " << x.value;
960 }
961 };
962
963 template <class Wrapper>
964 struct diagnostic<Wrapper, false, false>
965 {
966 static constexpr bool is_invisible = false;
967 static void print( std::ostream & os, Wrapper const & )
968 {
969 os << type<Wrapper>() << ": {Non-Printable}";
970 }
971 };
972
973 #ifndef BOOST_LEAF_NO_EXCEPTIONS
974 template <>
975 struct diagnostic<std::exception_ptr, false, false>
976 {
977 static constexpr bool is_invisible = true;
978 BOOST_LEAF_CONSTEXPR static void print( std::ostream &, std::exception_ptr const & )
979 {
980 }
981 };
982 #endif
983 }
984
985 } }
986
987 #endif
988 // <<< #include <boost/leaf/detail/print.hpp>
989 #line 21 "boost/leaf/error.hpp"
990 #include <system_error>
991 #include <type_traits>
992 #include <memory>
993 #include <string>
994
995 #if BOOST_LEAF_DIAGNOSTICS
996 # include <sstream>
997 # include <set>
998 #endif
999
1000 #define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y
1001 #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y)
1002 #define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__)
1003
1004 #define BOOST_LEAF_ASSIGN(v,r)\
1005 static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(r)>::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\
1006 auto && BOOST_LEAF_TMP = r;\
1007 if( !BOOST_LEAF_TMP )\
1008 return BOOST_LEAF_TMP.error();\
1009 v = std::forward<decltype(BOOST_LEAF_TMP)>(BOOST_LEAF_TMP).value()
1010
1011 #define BOOST_LEAF_AUTO(v, r)\
1012 BOOST_LEAF_ASSIGN(auto v, r)
1013
1014 #define BOOST_LEAF_CHECK(r)\
1015 {\
1016 static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(r)>::type>::value, "BOOST_LEAF_CHECK requires a result type");\
1017 auto && BOOST_LEAF_TMP = r;\
1018 if( !BOOST_LEAF_TMP )\
1019 return BOOST_LEAF_TMP.error();\
1020 }
1021
1022 #define BOOST_LEAF_NEW_ERROR ::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error
1023
1024 namespace boost { namespace leaf {
1025
1026 namespace leaf_detail
1027 {
1028 struct inject_loc
1029 {
1030 char const * const file;
1031 int const line;
1032 char const * const fn;
1033
1034 template <class T>
1035 friend T operator+( inject_loc loc, T && x ) noexcept
1036 {
1037 x.load_source_location_(loc.file, loc.line, loc.fn);
1038 return std::move(x);
1039 }
1040 };
1041 }
1042
1043 } }
1044
1045 ////////////////////////////////////////
1046
1047 #ifdef BOOST_LEAF_NO_EXCEPTIONS
1048
1049 namespace boost
1050 {
1051 BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined
1052 }
1053
1054 namespace boost { namespace leaf {
1055
1056 template <class T>
1057 BOOST_LEAF_NORETURN void throw_exception( T const & e )
1058 {
1059 ::boost::throw_exception(e);
1060 }
1061
1062 } }
1063
1064 #else
1065
1066 namespace boost { namespace leaf {
1067
1068 template <class T>
1069 BOOST_LEAF_NORETURN void throw_exception( T const & e )
1070 {
1071 throw e;
1072 }
1073
1074 } }
1075
1076 #endif
1077
1078 ////////////////////////////////////////
1079
1080 #ifdef BOOST_LEAF_NO_THREADS
1081
1082 # define BOOST_LEAF_THREAD_LOCAL
1083 namespace boost { namespace leaf {
1084 namespace leaf_detail
1085 {
1086 using atomic_unsigned_int = unsigned int;
1087 }
1088 } }
1089
1090 #else
1091
1092 # include <atomic>
1093 # include <thread>
1094 # define BOOST_LEAF_THREAD_LOCAL thread_local
1095 namespace boost { namespace leaf {
1096 namespace leaf_detail
1097 {
1098 using atomic_unsigned_int = std::atomic<unsigned int>;
1099 }
1100 } }
1101
1102 #endif
1103
1104 ////////////////////////////////////////
1105
1106 namespace boost { namespace leaf {
1107
1108 #if BOOST_LEAF_DIAGNOSTICS
1109
1110 namespace leaf_detail
1111 {
1112 class e_unexpected_count
1113 {
1114 public:
1115
1116 char const * (*first_type)();
1117 int count;
1118
1119 BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept:
1120 first_type(first_type),
1121 count(1)
1122 {
1123 }
1124
1125 template <class CharT, class Traits>
1126 void print( std::basic_ostream<CharT, Traits> & os ) const
1127 {
1128 BOOST_LEAF_ASSERT(first_type != 0);
1129 BOOST_LEAF_ASSERT(count>0);
1130 os << "Detected ";
1131 if( count==1 )
1132 os << "1 attempt to communicate an unexpected error object";
1133 else
1134 os << count << " attempts to communicate unexpected error objects, the first one";
1135 (os << " of type " << first_type() << '\n').flush();
1136 }
1137 };
1138
1139 template <>
1140 struct diagnostic<e_unexpected_count, false, false>
1141 {
1142 static constexpr bool is_invisible = true;
1143 BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { }
1144 };
1145
1146 class e_unexpected_info
1147 {
1148 std::string s_;
1149 std::set<char const *(*)()> already_;
1150
1151 public:
1152
1153 e_unexpected_info() noexcept
1154 {
1155 }
1156
1157 template <class E>
1158 void add(E && e)
1159 {
1160 if( !diagnostic<E>::is_invisible && already_.insert(&type<E>).second )
1161 {
1162 std::stringstream s;
1163 diagnostic<E>::print(s,e);
1164 (s << '\n').flush();
1165 s_ += s.str();
1166 }
1167 }
1168
1169 template <class CharT, class Traits>
1170 void print( std::basic_ostream<CharT, Traits> & os ) const
1171 {
1172 os << "Unhandled error objects:\n" << s_;
1173 }
1174 };
1175
1176 template <>
1177 struct diagnostic<e_unexpected_info, false, false>
1178 {
1179 static constexpr bool is_invisible = true;
1180 BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { }
1181 };
1182
1183 template <class=void>
1184 struct tl_unexpected_enabled
1185 {
1186 static BOOST_LEAF_THREAD_LOCAL int counter;
1187 };
1188
1189 template <class T>
1190 BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled<T>::counter;
1191 }
1192
1193 #endif
1194
1195 } }
1196
1197 ////////////////////////////////////////
1198
1199 namespace boost { namespace leaf {
1200
1201 struct e_source_location
1202 {
1203 char const * const file;
1204 int const line;
1205 char const * const function;
1206
1207 template <class CharT, class Traits>
1208 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, e_source_location const & x )
1209 {
1210 return os << leaf::type<e_source_location>() << ": " << x.file << '(' << x.line << ") in function " << x.function;
1211 }
1212 };
1213
1214 ////////////////////////////////////////
1215
1216 namespace leaf_detail
1217 {
1218 template <class E>
1219 class slot;
1220
1221 template <class E>
1222 struct tl_slot_ptr
1223 {
1224 static BOOST_LEAF_THREAD_LOCAL slot<E> * p;
1225 };
1226
1227 template <class E>
1228 BOOST_LEAF_THREAD_LOCAL slot<E> * tl_slot_ptr<E>::p;
1229
1230 template <class E>
1231 class slot:
1232 optional<E>
1233 {
1234 slot( slot const & ) = delete;
1235 slot & operator=( slot const & ) = delete;
1236
1237 using impl = optional<E>;
1238 slot<E> * * top_;
1239 slot<E> * prev_;
1240
1241 public:
1242
1243 BOOST_LEAF_CONSTEXPR slot() noexcept:
1244 top_(0)
1245 {
1246 }
1247
1248 BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept:
1249 optional<E>(std::move(x)),
1250 top_(0)
1251 {
1252 BOOST_LEAF_ASSERT(x.top_==0);
1253 }
1254
1255 BOOST_LEAF_CONSTEXPR void activate() noexcept
1256 {
1257 BOOST_LEAF_ASSERT(top_==0 || *top_!=this);
1258 top_ = &tl_slot_ptr<E>::p;
1259 prev_ = *top_;
1260 *top_ = this;
1261 }
1262
1263 BOOST_LEAF_CONSTEXPR void deactivate() noexcept
1264 {
1265 BOOST_LEAF_ASSERT(top_!=0 && *top_==this);
1266 *top_ = prev_;
1267 }
1268
1269 BOOST_LEAF_CONSTEXPR void propagate() noexcept;
1270
1271 template <class CharT, class Traits>
1272 void print( std::basic_ostream<CharT, Traits> & os, int key_to_print ) const
1273 {
1274 if( !diagnostic<E>::is_invisible )
1275 if( int k = this->key() )
1276 {
1277 if( key_to_print )
1278 {
1279 if( key_to_print!=k )
1280 return;
1281 }
1282 else
1283 os << '[' << k << ']';
1284 diagnostic<E>::print(os, value(k));
1285 (os << '\n').flush();
1286 }
1287 }
1288
1289 using impl::put;
1290 using impl::has_value;
1291 using impl::value;
1292 };
1293
1294 #if BOOST_LEAF_DIAGNOSTICS
1295
1296 template <class E>
1297 BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept
1298 {
1299 if( slot<e_unexpected_count> * sl = tl_slot_ptr<e_unexpected_count>::p )
1300 if( e_unexpected_count * unx = sl->has_value(err_id) )
1301 ++unx->count;
1302 else
1303 sl->put(err_id, e_unexpected_count(&type<E>));
1304 }
1305
1306 template <class E>
1307 BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept
1308 {
1309 if( slot<e_unexpected_info> * sl = tl_slot_ptr<e_unexpected_info>::p )
1310 if( e_unexpected_info * unx = sl->has_value(err_id) )
1311 unx->add(std::forward<E>(e));
1312 else
1313 sl->put(err_id, e_unexpected_info()).add(std::forward<E>(e));
1314 }
1315
1316 template <class E>
1317 BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept
1318 {
1319 load_unexpected_count<E>(err_id);
1320 load_unexpected_info(err_id, std::forward<E>(e));
1321 }
1322
1323 #endif
1324
1325 template <class E>
1326 BOOST_LEAF_CONSTEXPR inline void slot<E>::propagate() noexcept
1327 {
1328 BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this));
1329 if( prev_ )
1330 {
1331 impl & that_ = *prev_;
1332 if( that_.empty() )
1333 {
1334 impl & this_ = *this;
1335 that_ = std::move(this_);
1336 }
1337 }
1338 #if BOOST_LEAF_DIAGNOSTICS
1339 else
1340 {
1341 int c = tl_unexpected_enabled<>::counter;
1342 BOOST_LEAF_ASSERT(c>=0);
1343 if( c )
1344 if( int err_id = impl::key() )
1345 load_unexpected(err_id, std::move(*this).value(err_id));
1346 }
1347 #endif
1348 }
1349
1350 template <class E>
1351 BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept
1352 {
1353 static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
1354 using T = typename std::decay<E>::type;
1355 BOOST_LEAF_ASSERT((err_id&3)==1);
1356 if( slot<T> * p = tl_slot_ptr<T>::p )
1357 (void) p->put(err_id, std::forward<E>(e));
1358 #if BOOST_LEAF_DIAGNOSTICS
1359 else
1360 {
1361 int c = tl_unexpected_enabled<>::counter;
1362 BOOST_LEAF_ASSERT(c>=0);
1363 if( c )
1364 load_unexpected(err_id, std::forward<E>(e));
1365 }
1366 #endif
1367 return 0;
1368 }
1369
1370 template <class F>
1371 BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept
1372 {
1373 static_assert(function_traits<F>::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference");
1374 using E = typename std::decay<fn_arg_type<F,0>>::type;
1375 static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
1376 BOOST_LEAF_ASSERT((err_id&3)==1);
1377 if( auto sl = tl_slot_ptr<E>::p )
1378 if( auto v = sl->has_value(err_id) )
1379 (void) std::forward<F>(f)(*v);
1380 else
1381 (void) std::forward<F>(f)(sl->put(err_id,E()));
1382 return 0;
1383 }
1384 }
1385
1386 ////////////////////////////////////////
1387
1388 namespace leaf_detail
1389 {
1390 template <class=void>
1391 struct id_factory
1392 {
1393 static atomic_unsigned_int counter;
1394 static BOOST_LEAF_THREAD_LOCAL unsigned current_id;
1395
1396 BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept
1397 {
1398 auto id = (counter+=4);
1399 BOOST_LEAF_ASSERT((id&3)==1);
1400 return id;
1401 }
1402 };
1403
1404 template <class T>
1405 atomic_unsigned_int id_factory<T>::counter(-3);
1406
1407 template <class T>
1408 BOOST_LEAF_THREAD_LOCAL unsigned id_factory<T>::current_id(0);
1409
1410 inline int current_id() noexcept
1411 {
1412 auto id = id_factory<>::current_id;
1413 BOOST_LEAF_ASSERT(id==0 || (id&3)==1);
1414 return id;
1415 }
1416
1417 inline int new_id() noexcept
1418 {
1419 auto id = id_factory<>::generate_next_id();
1420 return id_factory<>::current_id = id;
1421 }
1422 }
1423
1424 ////////////////////////////////////////
1425
1426 namespace leaf_detail
1427 {
1428 template <class T, int Arity = function_traits<T>::arity>
1429 struct load_item
1430 {
1431 static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument");
1432 };
1433
1434 template <class E>
1435 struct load_item<E, -1>
1436 {
1437 BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept
1438 {
1439 return load_slot(err_id, std::forward<E>(e));
1440 }
1441 };
1442
1443 template <class F>
1444 struct load_item<F, 0>
1445 {
1446 BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept
1447 {
1448 return load_slot(err_id, std::forward<F>(f)());
1449 }
1450 };
1451
1452 template <class F>
1453 struct load_item<F, 1>
1454 {
1455 BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept
1456 {
1457 return accumulate_slot(err_id, std::forward<F>(f));
1458 }
1459 };
1460 }
1461
1462 ////////////////////////////////////////
1463
1464 namespace leaf_detail
1465 {
1466 class leaf_category final: public std::error_category
1467 {
1468 bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; }
1469 bool equivalent( std::error_code const &, int ) const noexcept final override { return false; }
1470 char const * name() const noexcept final override { return "LEAF error"; }
1471 std::string message( int condition ) const final override { return name(); }
1472 public:
1473 ~leaf_category() noexcept final override { }
1474 };
1475
1476 template <class=void>
1477 struct get_error_category
1478 {
1479 static leaf_category cat;
1480 };
1481
1482 template <class T>
1483 leaf_category get_error_category<T>::cat;
1484
1485 inline int import_error_code( std::error_code const & ec ) noexcept
1486 {
1487 if( int err_id = ec.value() )
1488 {
1489 std::error_category const & cat = get_error_category<>::cat;
1490 if( &ec.category()==&cat )
1491 {
1492 BOOST_LEAF_ASSERT((err_id&3)==1);
1493 return (err_id&~3)|1;
1494 }
1495 else
1496 {
1497 err_id = new_id();
1498 (void) load_slot(err_id, ec);
1499 return (err_id&~3)|1;
1500 }
1501 }
1502 else
1503 return 0;
1504 }
1505 }
1506
1507 inline bool is_error_id( std::error_code const & ec ) noexcept
1508 {
1509 bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat);
1510 BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1));
1511 return res;
1512 }
1513
1514 ////////////////////////////////////////
1515
1516 class error_id;
1517
1518 namespace leaf_detail
1519 {
1520 BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept;
1521 }
1522
1523 class error_id
1524 {
1525 friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept;
1526
1527 int value_;
1528
1529 BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept:
1530 value_(value)
1531 {
1532 BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1));
1533 }
1534
1535 public:
1536
1537 BOOST_LEAF_CONSTEXPR error_id() noexcept:
1538 value_(0)
1539 {
1540 }
1541
1542 error_id( std::error_code const & ec ) noexcept:
1543 value_(leaf_detail::import_error_code(ec))
1544 {
1545 BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1));
1546 }
1547
1548 template <class Enum>
1549 error_id( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
1550 value_(leaf_detail::import_error_code(e))
1551 {
1552 }
1553
1554 BOOST_LEAF_CONSTEXPR error_id load() const noexcept
1555 {
1556 return *this;
1557 }
1558
1559 template <class... Item>
1560 BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept
1561 {
1562 if( int err_id = value() )
1563 {
1564 int const unused[ ] = { 42, leaf_detail::load_item<Item>::load(err_id, std::forward<Item>(item))... };
1565 (void) unused;
1566 }
1567 return *this;
1568 }
1569
1570 std::error_code to_error_code() const noexcept
1571 {
1572 return std::error_code(value_, leaf_detail::get_error_category<>::cat);
1573 }
1574
1575 BOOST_LEAF_CONSTEXPR int value() const noexcept
1576 {
1577 if( int v = value_ )
1578 {
1579 BOOST_LEAF_ASSERT((v&3)==1);
1580 return (v&~3)|1;
1581 }
1582 else
1583 return 0;
1584 }
1585
1586 BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept
1587 {
1588 return value_ != 0;
1589 }
1590
1591 BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept
1592 {
1593 return a.value_ == b.value_;
1594 }
1595
1596 BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept
1597 {
1598 return !(a == b);
1599 }
1600
1601 BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept
1602 {
1603 return a.value_ < b.value_;
1604 }
1605
1606 template <class CharT, class Traits>
1607 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_id x )
1608 {
1609 return os << x.value_;
1610 }
1611
1612 BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept
1613 {
1614 BOOST_LEAF_ASSERT(file&&*file);
1615 BOOST_LEAF_ASSERT(line>0);
1616 BOOST_LEAF_ASSERT(function&&*function);
1617 BOOST_LEAF_ASSERT(value_);
1618 (void) load(e_source_location {file,line,function});
1619 }
1620 };
1621
1622 namespace leaf_detail
1623 {
1624 BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept
1625 {
1626 BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1);
1627 return error_id((err_id&~3)|1);
1628 }
1629 }
1630
1631 inline error_id new_error() noexcept
1632 {
1633 return leaf_detail::make_error_id(leaf_detail::new_id());
1634 }
1635
1636 template <class... Item>
1637 inline error_id new_error( Item && ... item ) noexcept
1638 {
1639 return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward<Item>(item)...);
1640 }
1641
1642 inline error_id current_error() noexcept
1643 {
1644 return leaf_detail::make_error_id(leaf_detail::current_id());
1645 }
1646
1647 ////////////////////////////////////////////
1648
1649 class polymorphic_context
1650 {
1651 protected:
1652
1653 polymorphic_context() noexcept = default;
1654 ~polymorphic_context() noexcept = default;
1655
1656 public:
1657
1658 virtual error_id propagate_captured_errors() noexcept = 0;
1659 virtual void activate() noexcept = 0;
1660 virtual void deactivate() noexcept = 0;
1661 virtual void propagate() noexcept = 0;
1662 virtual bool is_active() const noexcept = 0;
1663 virtual void print( std::ostream & ) const = 0;
1664 error_id captured_id_;
1665 };
1666
1667 using context_ptr = std::shared_ptr<polymorphic_context>;
1668
1669 ////////////////////////////////////////////
1670
1671 template <class Ctx>
1672 class context_activator
1673 {
1674 context_activator( context_activator const & ) = delete;
1675 context_activator & operator=( context_activator const & ) = delete;
1676
1677 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1678 int const uncaught_exceptions_;
1679 #endif
1680 Ctx * ctx_;
1681
1682 public:
1683
1684 explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept:
1685 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1686 uncaught_exceptions_(std::uncaught_exceptions()),
1687 #endif
1688 ctx_(ctx.is_active() ? 0 : &ctx)
1689 {
1690 if( ctx_ )
1691 ctx_->activate();
1692 }
1693
1694 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept:
1695 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1696 uncaught_exceptions_(x.uncaught_exceptions_),
1697 #endif
1698 ctx_(x.ctx_)
1699 {
1700 x.ctx_ = 0;
1701 }
1702
1703 BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept
1704 {
1705 if( !ctx_ )
1706 return;
1707 if( ctx_->is_active() )
1708 ctx_->deactivate();
1709 #ifndef BOOST_LEAF_NO_EXCEPTIONS
1710 # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1711 if( std::uncaught_exceptions() > uncaught_exceptions_ )
1712 # else
1713 if( std::uncaught_exception() )
1714 # endif
1715 ctx_->propagate();
1716 #endif
1717 }
1718 };
1719
1720 template <class Ctx>
1721 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context(Ctx & ctx) noexcept
1722 {
1723 return context_activator<Ctx>(ctx);
1724 }
1725
1726 ////////////////////////////////////////////
1727
1728 template <class R>
1729 struct is_result_type: std::false_type
1730 {
1731 };
1732
1733 template <class R>
1734 struct is_result_type<R const>: is_result_type<R>
1735 {
1736 };
1737
1738 } }
1739
1740 #undef BOOST_LEAF_THREAD_LOCAL
1741
1742 #endif
1743 // <<< #include <boost/leaf/error.hpp>
1744 #line 20 "boost/leaf/exception.hpp"
1745 #include <exception>
1746
1747 #define BOOST_LEAF_EXCEPTION ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception
1748 #define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::leaf_detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception
1749
1750 ////////////////////////////////////////
1751
1752 namespace boost { namespace leaf {
1753
1754 namespace leaf_detail
1755 {
1756 struct throw_with_loc
1757 {
1758 char const * const file;
1759 int const line;
1760 char const * const fn;
1761
1762 template <class Ex>
1763 [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex )
1764 {
1765 ex.load_source_location_(loc.file, loc.line, loc.fn);
1766 ::boost::leaf::throw_exception(ex);
1767 }
1768 };
1769 }
1770
1771 } }
1772
1773 ////////////////////////////////////////
1774
1775 namespace boost { namespace leaf {
1776
1777 namespace leaf_detail
1778 {
1779 inline void enforce_std_exception( std::exception const & ) noexcept { }
1780
1781 class exception_base
1782 {
1783 std::shared_ptr<void const> auto_id_bump_;
1784 public:
1785
1786 virtual error_id get_error_id() const noexcept = 0;
1787
1788 protected:
1789
1790 exception_base():
1791 auto_id_bump_(0, [](void const *) { (void) new_id(); })
1792 {
1793 }
1794
1795 ~exception_base() noexcept { }
1796 };
1797
1798 template <class Ex>
1799 class exception:
1800 public Ex,
1801 public exception_base,
1802 public error_id
1803 {
1804 error_id get_error_id() const noexcept final override
1805 {
1806 return *this;
1807 }
1808
1809 public:
1810
1811 exception( exception const & ) = default;
1812 exception( exception && ) = default;
1813
1814 BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept:
1815 Ex(std::move(ex)),
1816 error_id(id)
1817 {
1818 enforce_std_exception(*this);
1819 }
1820
1821 explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept:
1822 error_id(id)
1823 {
1824 enforce_std_exception(*this);
1825 }
1826 };
1827
1828 template <class... T>
1829 struct at_least_one_derives_from_std_exception;
1830
1831 template <>
1832 struct at_least_one_derives_from_std_exception<>: std::false_type { };
1833
1834 template <class T, class... Rest>
1835 struct at_least_one_derives_from_std_exception<T, Rest...>
1836 {
1837 constexpr static const bool value = std::is_base_of<std::exception,T>::value || at_least_one_derives_from_std_exception<Rest...>::value;
1838 };
1839 }
1840
1841 template <class Ex, class... E>
1842 inline
1843 typename std::enable_if<std::is_base_of<std::exception,Ex>::value, leaf_detail::exception<Ex>>::type
1844 exception( Ex && ex, E && ... e ) noexcept
1845 {
1846 static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
1847 auto id = leaf::new_error(std::forward<E>(e)...);
1848 return leaf_detail::exception<Ex>(id, std::forward<Ex>(ex));
1849 }
1850
1851 template <class E1, class... E>
1852 inline
1853 typename std::enable_if<!std::is_base_of<std::exception,E1>::value, leaf_detail::exception<std::exception>>::type
1854 exception( E1 && car, E && ... cdr ) noexcept
1855 {
1856 static_assert(!leaf_detail::at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
1857 auto id = leaf::new_error(std::forward<E1>(car), std::forward<E>(cdr)...);
1858 return leaf_detail::exception<std::exception>(id);
1859 }
1860
1861 inline leaf_detail::exception<std::exception> exception() noexcept
1862 {
1863 return leaf_detail::exception<std::exception>(leaf::new_error());
1864 }
1865
1866 } }
1867
1868 #endif
1869 // <<< #include <boost/leaf/exception.hpp>
1870 #line 20 "boost/leaf/capture.hpp"
1871 // >>> #include <boost/leaf/on_error.hpp>
1872 #line 1 "boost/leaf/on_error.hpp"
1873 #ifndef BOOST_LEAF_ON_ERROR_HPP_INCLUDED
1874 #define BOOST_LEAF_ON_ERROR_HPP_INCLUDED
1875
1876 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
1877
1878 // Distributed under the Boost Software License, Version 1.0. (See accompanying
1879 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1880
1881 #ifndef BOOST_LEAF_ENABLE_WARNINGS
1882 # if defined(__clang__)
1883 # pragma clang system_header
1884 # elif (__GNUC__*100+__GNUC_MINOR__>301)
1885 # pragma GCC system_header
1886 # elif defined(_MSC_VER)
1887 # pragma warning(push,1)
1888 # endif
1889 #endif
1890
1891
1892 namespace boost { namespace leaf {
1893
1894 class error_monitor
1895 {
1896 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1897 int const uncaught_exceptions_;
1898 #endif
1899 int const err_id_;
1900
1901 public:
1902
1903 error_monitor() noexcept:
1904 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1905 uncaught_exceptions_(std::uncaught_exceptions()),
1906 #endif
1907 err_id_(leaf_detail::current_id())
1908 {
1909 }
1910
1911 int check_id() const noexcept
1912 {
1913 int err_id = leaf_detail::current_id();
1914 if( err_id != err_id_ )
1915 return err_id;
1916 else
1917 {
1918 #ifndef BOOST_LEAF_NO_EXCEPTIONS
1919 # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
1920 if( std::uncaught_exceptions() > uncaught_exceptions_ )
1921 # else
1922 if( std::uncaught_exception() )
1923 # endif
1924 return leaf_detail::new_id();
1925 #endif
1926 return 0;
1927 }
1928 }
1929
1930 int get_id() const noexcept
1931 {
1932 int err_id = leaf_detail::current_id();
1933 if( err_id != err_id_ )
1934 return err_id;
1935 else
1936 return leaf_detail::new_id();
1937 }
1938
1939 error_id check() const noexcept
1940 {
1941 return leaf_detail::make_error_id(check_id());
1942 }
1943
1944 error_id assigned_error_id() const noexcept
1945 {
1946 return leaf_detail::make_error_id(get_id());
1947 }
1948 };
1949
1950 ////////////////////////////////////////////
1951
1952 namespace leaf_detail
1953 {
1954 template <int I, class Tuple>
1955 struct tuple_for_each_preload
1956 {
1957 BOOST_LEAF_CONSTEXPR static void trigger( Tuple & tup, int err_id ) noexcept
1958 {
1959 BOOST_LEAF_ASSERT((err_id&3)==1);
1960 tuple_for_each_preload<I-1,Tuple>::trigger(tup,err_id);
1961 std::get<I-1>(tup).trigger(err_id);
1962 }
1963 };
1964
1965 template <class Tuple>
1966 struct tuple_for_each_preload<0, Tuple>
1967 {
1968 BOOST_LEAF_CONSTEXPR static void trigger( Tuple const &, int ) noexcept { }
1969 };
1970
1971 template <class E>
1972 class preloaded_item
1973 {
1974 using decay_E = typename std::decay<E>::type;
1975 slot<decay_E> * s_;
1976 decay_E e_;
1977
1978 public:
1979
1980 BOOST_LEAF_CONSTEXPR preloaded_item( E && e ):
1981 s_(tl_slot_ptr<decay_E>::p),
1982 e_(std::forward<E>(e))
1983 {
1984 }
1985
1986 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
1987 {
1988 BOOST_LEAF_ASSERT((err_id&3)==1);
1989 if( s_ )
1990 {
1991 if( !s_->has_value(err_id) )
1992 s_->put(err_id, std::move(e_));
1993 }
1994 #if BOOST_LEAF_DIAGNOSTICS
1995 else
1996 {
1997 int c = tl_unexpected_enabled<>::counter;
1998 BOOST_LEAF_ASSERT(c>=0);
1999 if( c )
2000 load_unexpected(err_id, std::move(e_));
2001 }
2002 #endif
2003 }
2004 };
2005
2006 template <class F>
2007 class deferred_item
2008 {
2009 using E = decltype(std::declval<F>()());
2010 slot<E> * s_;
2011 F f_;
2012
2013 public:
2014
2015 BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept:
2016 s_(tl_slot_ptr<E>::p),
2017 f_(std::forward<F>(f))
2018 {
2019 }
2020
2021 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
2022 {
2023 BOOST_LEAF_ASSERT((err_id&3)==1);
2024 if( s_ )
2025 {
2026 if( !s_->has_value(err_id) )
2027 s_->put(err_id, f_());
2028 }
2029 #if BOOST_LEAF_DIAGNOSTICS
2030 else
2031 {
2032 int c = tl_unexpected_enabled<>::counter;
2033 BOOST_LEAF_ASSERT(c>=0);
2034 if( c )
2035 load_unexpected(err_id, std::forward<E>(f_()));
2036 }
2037 #endif
2038 }
2039 };
2040
2041 template <class F, class A0 = fn_arg_type<F,0>, int arity = function_traits<F>::arity>
2042 class accumulating_item;
2043
2044 template <class F, class A0>
2045 class accumulating_item<F, A0 &, 1>
2046 {
2047 using E = A0;
2048 slot<E> * s_;
2049 F f_;
2050
2051 public:
2052
2053 BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept:
2054 s_(tl_slot_ptr<E>::p),
2055 f_(std::forward<F>(f))
2056 {
2057 }
2058
2059 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
2060 {
2061 BOOST_LEAF_ASSERT((err_id&3)==1);
2062 if( s_ )
2063 if( E * e = s_->has_value(err_id) )
2064 (void) f_(*e);
2065 else
2066 (void) f_(s_->put(err_id, E()));
2067 }
2068 };
2069
2070 template <class... Item>
2071 class preloaded
2072 {
2073 preloaded & operator=( preloaded const & ) = delete;
2074
2075 std::tuple<Item...> p_;
2076 bool moved_;
2077 error_monitor id_;
2078
2079 public:
2080
2081 BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ):
2082 p_(std::forward<Item>(i)...),
2083 moved_(false)
2084 {
2085 }
2086
2087 BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept:
2088 p_(std::move(x.p_)),
2089 moved_(false),
2090 id_(std::move(x.id_))
2091 {
2092 x.moved_ = true;
2093 }
2094
2095 ~preloaded() noexcept
2096 {
2097 if( moved_ )
2098 return;
2099 if( auto id = id_.check_id() )
2100 tuple_for_each_preload<sizeof...(Item),decltype(p_)>::trigger(p_,id);
2101 }
2102 };
2103
2104 template <class T, int arity = function_traits<T>::arity>
2105 struct deduce_item_type;
2106
2107 template <class T>
2108 struct deduce_item_type<T, -1>
2109 {
2110 using type = preloaded_item<T>;
2111 };
2112
2113 template <class F>
2114 struct deduce_item_type<F, 0>
2115 {
2116 using type = deferred_item<F>;
2117 };
2118
2119 template <class F>
2120 struct deduce_item_type<F, 1>
2121 {
2122 using type = accumulating_item<F>;
2123 };
2124 }
2125
2126 template <class... Item>
2127 BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
2128 leaf_detail::preloaded<typename leaf_detail::deduce_item_type<Item>::type...>
2129 on_error( Item && ... i )
2130 {
2131 return leaf_detail::preloaded<typename leaf_detail::deduce_item_type<Item>::type...>(std::forward<Item>(i)...);
2132 }
2133
2134 } }
2135
2136 #endif
2137 // <<< #include <boost/leaf/on_error.hpp>
2138 #line 21 "boost/leaf/capture.hpp"
2139
2140 namespace boost { namespace leaf {
2141
2142 namespace leaf_detail
2143 {
2144 template <class R, bool IsResult = is_result_type<R>::value>
2145 struct is_result_tag;
2146
2147 template <class R>
2148 struct is_result_tag<R, false>
2149 {
2150 };
2151
2152 template <class R>
2153 struct is_result_tag<R, true>
2154 {
2155 };
2156 }
2157
2158 #ifdef BOOST_LEAF_NO_EXCEPTIONS
2159
2160 namespace leaf_detail
2161 {
2162 template <class R, class F, class... A>
2163 inline
2164 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
2165 capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a) noexcept
2166 {
2167 auto active_context = activate_context(*ctx);
2168 return std::forward<F>(f)(std::forward<A>(a)...);
2169 }
2170
2171 template <class R, class F, class... A>
2172 inline
2173 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
2174 capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a) noexcept
2175 {
2176 auto active_context = activate_context(*ctx);
2177 if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
2178 return r;
2179 else
2180 {
2181 ctx->captured_id_ = r.error();
2182 return std::move(ctx);
2183 }
2184 }
2185
2186 template <class R, class Future>
2187 inline
2188 decltype(std::declval<Future>().get())
2189 future_get_impl(is_result_tag<R, false>, Future & fut) noexcept
2190 {
2191 return fut.get();
2192 }
2193
2194 template <class R, class Future>
2195 inline
2196 decltype(std::declval<Future>().get())
2197 future_get_impl(is_result_tag<R, true>, Future & fut) noexcept
2198 {
2199 if( auto r = fut.get() )
2200 return r;
2201 else
2202 return error_id(r.error()); // unloads
2203 }
2204 }
2205
2206 #else
2207
2208 namespace leaf_detail
2209 {
2210 class capturing_exception:
2211 public std::exception
2212 {
2213 std::exception_ptr ex_;
2214 context_ptr ctx_;
2215
2216 public:
2217
2218 capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept:
2219 ex_(std::move(ex)),
2220 ctx_(std::move(ctx))
2221 {
2222 BOOST_LEAF_ASSERT(ex_);
2223 BOOST_LEAF_ASSERT(ctx_);
2224 BOOST_LEAF_ASSERT(ctx_->captured_id_);
2225 }
2226
2227 [[noreturn]] void unload_and_rethrow_original_exception() const
2228 {
2229 BOOST_LEAF_ASSERT(ctx_->captured_id_);
2230 auto active_context = activate_context(*ctx_);
2231 id_factory<>::current_id = ctx_->captured_id_.value();
2232 std::rethrow_exception(ex_);
2233 }
2234
2235 template <class CharT, class Traits>
2236 void print( std::basic_ostream<CharT, Traits> & os ) const
2237 {
2238 ctx_->print(os);
2239 }
2240 };
2241
2242 template <class R, class F, class... A>
2243 inline
2244 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
2245 capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a)
2246 {
2247 auto active_context = activate_context(*ctx);
2248 error_monitor cur_err;
2249 try
2250 {
2251 return std::forward<F>(f)(std::forward<A>(a)...);
2252 }
2253 catch( capturing_exception const & )
2254 {
2255 throw;
2256 }
2257 catch( exception_base const & e )
2258 {
2259 ctx->captured_id_ = e.get_error_id();
2260 throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
2261 }
2262 catch(...)
2263 {
2264 ctx->captured_id_ = cur_err.assigned_error_id();
2265 throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
2266 }
2267 }
2268
2269 template <class R, class F, class... A>
2270 inline
2271 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
2272 capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a)
2273 {
2274 auto active_context = activate_context(*ctx);
2275 error_monitor cur_err;
2276 try
2277 {
2278 if( auto && r = std::forward<F>(f)(std::forward<A>(a)...) )
2279 return std::move(r);
2280 else
2281 {
2282 ctx->captured_id_ = r.error();
2283 return std::move(ctx);
2284 }
2285 }
2286 catch( capturing_exception const & )
2287 {
2288 throw;
2289 }
2290 catch( exception_base const & e )
2291 {
2292 ctx->captured_id_ = e.get_error_id();
2293 throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
2294 }
2295 catch(...)
2296 {
2297 ctx->captured_id_ = cur_err.assigned_error_id();
2298 throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
2299 }
2300 }
2301
2302 template <class R, class Future>
2303 inline
2304 decltype(std::declval<Future>().get())
2305 future_get_impl(is_result_tag<R, false>, Future & fut )
2306 {
2307 try
2308 {
2309 return fut.get();
2310 }
2311 catch( capturing_exception const & cap )
2312 {
2313 cap.unload_and_rethrow_original_exception();
2314 }
2315 }
2316
2317 template <class R, class Future>
2318 inline
2319 decltype(std::declval<Future>().get())
2320 future_get_impl(is_result_tag<R, true>, Future & fut )
2321 {
2322 try
2323 {
2324 if( auto r = fut.get() )
2325 return r;
2326 else
2327 return error_id(r.error()); // unloads
2328 }
2329 catch( capturing_exception const & cap )
2330 {
2331 cap.unload_and_rethrow_original_exception();
2332 }
2333 }
2334 }
2335
2336 #endif
2337
2338 template <class F, class... A>
2339 inline
2340 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
2341 capture(context_ptr && ctx, F && f, A... a)
2342 {
2343 using namespace leaf_detail;
2344 return capture_impl(is_result_tag<decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))>(), std::move(ctx), std::forward<F>(f), std::forward<A>(a)...);
2345 }
2346
2347 template <class Future>
2348 inline
2349 decltype(std::declval<Future>().get())
2350 future_get( Future & fut )
2351 {
2352 using namespace leaf_detail;
2353 return future_get_impl(is_result_tag<decltype(std::declval<Future>().get())>(), fut);
2354 }
2355
2356 ////////////////////////////////////////
2357
2358 #ifndef BOOST_LEAF_NO_EXCEPTIONS
2359
2360 template <class T>
2361 class result;
2362
2363 namespace leaf_detail
2364 {
2365 inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> )
2366 {
2367 return leaf::new_error(std::current_exception());
2368 }
2369
2370 template <class Ex1, class... Ex>
2371 inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
2372 {
2373 if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
2374 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
2375 else
2376 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
2377 }
2378
2379 template <class T>
2380 struct deduce_exception_to_result_return_type_impl
2381 {
2382 using type = result<T>;
2383 };
2384
2385 template <class T>
2386 struct deduce_exception_to_result_return_type_impl<result<T>>
2387 {
2388 using type = result<T>;
2389 };
2390
2391 template <class T>
2392 using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
2393 }
2394
2395 template <class... Ex, class F>
2396 inline
2397 leaf_detail::deduce_exception_to_result_return_type<leaf_detail::fn_return_type<F>>
2398 exception_to_result( F && f ) noexcept
2399 {
2400 try
2401 {
2402 return std::forward<F>(f)();
2403 }
2404 catch( std::exception const & ex )
2405 {
2406 return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
2407 }
2408 catch(...)
2409 {
2410 return leaf::new_error(std::current_exception());
2411 }
2412 }
2413
2414 #endif
2415
2416 } }
2417
2418 #endif
2419 // <<< #include <boost/leaf/capture.hpp>
2420 #line 10 "../../include/boost/leaf/detail/all.hpp"
2421 // >>> #include <boost/leaf/common.hpp>
2422 #line 1 "boost/leaf/common.hpp"
2423 #ifndef BOOST_LEAF_COMMON_HPP_INCLUDED
2424 #define BOOST_LEAF_COMMON_HPP_INCLUDED
2425
2426 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2427
2428 // Distributed under the Boost Software License, Version 1.0. (See accompanying
2429 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2430
2431 #ifndef BOOST_LEAF_ENABLE_WARNINGS
2432 # if defined(__clang__)
2433 # pragma clang system_header
2434 # elif (__GNUC__*100+__GNUC_MINOR__>301)
2435 # pragma GCC system_header
2436 # elif defined(_MSC_VER)
2437 # pragma warning(push,1)
2438 # endif
2439 #endif
2440
2441 #include <string>
2442 #include <cerrno>
2443 #ifdef _WIN32
2444 # include <Windows.h>
2445 # include <cstring>
2446 #ifdef min
2447 # undef min
2448 #endif
2449 #ifdef max
2450 # undef max
2451 #endif
2452 #endif
2453
2454 namespace boost { namespace leaf {
2455
2456 struct e_api_function { char const * value; };
2457
2458 struct e_file_name { std::string value; };
2459
2460 struct e_errno
2461 {
2462 int value;
2463
2464 template <class CharT, class Traits>
2465 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, e_errno const & err )
2466 {
2467 return os << type<e_errno>() << ": " << err.value << ", \"" << std::strerror(err.value) << '"';
2468 }
2469 };
2470
2471 struct e_type_info_name { char const * value; };
2472
2473 struct e_at_line { int value; };
2474
2475 namespace windows
2476 {
2477 struct e_LastError
2478 {
2479 unsigned value;
2480
2481 #ifdef _WIN32
2482 template <class CharT, class Traits>
2483 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> os, e_LastError const & err )
2484 {
2485 struct msg_buf
2486 {
2487 LPVOID * p;
2488 msg_buf(): p(0) { }
2489 ~msg_buf() noexcept { if(p) LocalFree(p); }
2490 };
2491 msg_buf mb;
2492 if( FormatMessageA(
2493 FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
2494 0,
2495 err.value,
2496 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
2497 (LPSTR)&mb.p,
2498 0,
2499 0) )
2500 {
2501 BOOST_LEAF_ASSERT(mb.p != 0);
2502 char * z = std::strchr((LPSTR)mb.p,0);
2503 if( z[-1] == '\n' )
2504 *--z = 0;
2505 if( z[-1] == '\r' )
2506 *--z = 0;
2507 return os << type<e_LastError>() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"';
2508 }
2509 return os;
2510 }
2511 #else
2512 // TODO : Other platforms
2513 #endif
2514 };
2515 }
2516
2517 } }
2518
2519 #endif
2520 // <<< #include <boost/leaf/common.hpp>
2521 #line 11 "../../include/boost/leaf/detail/all.hpp"
2522 // >>> #include <boost/leaf/context.hpp>
2523 #line 1 "boost/leaf/context.hpp"
2524 #ifndef BOOST_LEAF_CONTEXT_HPP_INCLUDED
2525 #define BOOST_LEAF_CONTEXT_HPP_INCLUDED
2526
2527 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2528
2529 // Distributed under the Boost Software License, Version 1.0. (See accompanying
2530 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2531
2532 #ifndef BOOST_LEAF_ENABLE_WARNINGS
2533 # if defined(__clang__)
2534 # pragma clang system_header
2535 # elif (__GNUC__*100+__GNUC_MINOR__>301)
2536 # pragma GCC system_header
2537 # elif defined(_MSC_VER)
2538 # pragma warning(push,1)
2539 # endif
2540 #endif
2541
2542
2543 namespace boost { namespace leaf {
2544
2545 class error_info;
2546 class diagnostic_info;
2547 class verbose_diagnostic_info;
2548
2549 template <class>
2550 struct is_predicate: std::false_type
2551 {
2552 };
2553
2554 namespace leaf_detail
2555 {
2556 template <class T>
2557 struct is_exception: std::is_base_of<std::exception, typename std::decay<T>::type>
2558 {
2559 };
2560
2561 template <class E>
2562 struct handler_argument_traits;
2563
2564 template <class E, bool IsPredicate = is_predicate<E>::value>
2565 struct handler_argument_traits_defaults;
2566
2567 template <class E>
2568 struct handler_argument_traits_defaults<E, false>
2569 {
2570 using error_type = typename std::decay<E>::type;
2571 constexpr static bool always_available = false;
2572
2573 template <class Tup>
2574 BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept;
2575
2576 template <class Tup>
2577 BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept;
2578
2579 template <class Tup>
2580 BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept
2581 {
2582 return *check(tup, ei);
2583 }
2584
2585 static_assert(!is_predicate<error_type>::value, "Handlers must take predicate arguments by value");
2586 static_assert(!std::is_same<E, error_info>::value, "Handlers must take leaf::error_info arguments by const &");
2587 static_assert(!std::is_same<E, diagnostic_info>::value, "Handlers must take leaf::diagnostic_info arguments by const &");
2588 static_assert(!std::is_same<E, verbose_diagnostic_info>::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &");
2589 };
2590
2591 template <class Pred>
2592 struct handler_argument_traits_defaults<Pred, true>: handler_argument_traits<typename Pred::error_type>
2593 {
2594 using base = handler_argument_traits<typename Pred::error_type>;
2595 static_assert(!base::always_available, "Predicates can't use types that are always_available");
2596
2597 template <class Tup>
2598 BOOST_LEAF_CONSTEXPR static bool check( Tup const & tup, error_info const & ei ) noexcept
2599 {
2600 auto e = base::check(tup, ei);
2601 return e && Pred::evaluate(*e);
2602 };
2603
2604 template <class Tup>
2605 BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept
2606 {
2607 return Pred{*base::check(tup, ei)};
2608 }
2609 };
2610
2611 template <class E>
2612 struct handler_argument_always_available
2613 {
2614 using error_type = E;
2615 constexpr static bool always_available = true;
2616
2617 template <class Tup>
2618 BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept
2619 {
2620 return true;
2621 };
2622 };
2623
2624 template <class E>
2625 struct handler_argument_traits: handler_argument_traits_defaults<E>
2626 {
2627 };
2628
2629 template <>
2630 struct handler_argument_traits<void>
2631 {
2632 using error_type = void;
2633 constexpr static bool always_available = false;
2634
2635 template <class Tup>
2636 BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept;
2637 };
2638
2639 template <class E>
2640 struct handler_argument_traits<E &&>
2641 {
2642 static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments");
2643 };
2644
2645 template <class E>
2646 struct handler_argument_traits<E *>: handler_argument_always_available<typename std::remove_const<E>::type>
2647 {
2648 template <class Tup>
2649 BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept
2650 {
2651 return handler_argument_traits_defaults<E>::check(tup, ei);
2652 }
2653 };
2654
2655 template <>
2656 struct handler_argument_traits<error_info const &>: handler_argument_always_available<void>
2657 {
2658 template <class Tup>
2659 BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept
2660 {
2661 return ei;
2662 }
2663 };
2664
2665 template <class E>
2666 struct handler_argument_traits_require_by_value
2667 {
2668 static_assert(sizeof(E) == 0, "Error handlers must take this type by value");
2669 };
2670 }
2671
2672 ////////////////////////////////////////
2673
2674 namespace leaf_detail
2675 {
2676 template <int I, class Tuple>
2677 struct tuple_for_each
2678 {
2679 BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept
2680 {
2681 static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
2682 tuple_for_each<I-1,Tuple>::activate(tup);
2683 std::get<I-1>(tup).activate();
2684 }
2685
2686 BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept
2687 {
2688 static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
2689 std::get<I-1>(tup).deactivate();
2690 tuple_for_each<I-1,Tuple>::deactivate(tup);
2691 }
2692
2693 BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept
2694 {
2695 static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
2696 auto & sl = std::get<I-1>(tup);
2697 sl.propagate();
2698 tuple_for_each<I-1,Tuple>::propagate(tup);
2699 }
2700
2701 BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept
2702 {
2703 static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
2704 auto & sl = std::get<I-1>(tup);
2705 if( sl.has_value(err_id) )
2706 load_slot(err_id, std::move(sl).value(err_id));
2707 tuple_for_each<I-1,Tuple>::propagate_captured(tup, err_id);
2708 }
2709
2710 static void print( std::ostream & os, void const * tup, int key_to_print )
2711 {
2712 BOOST_LEAF_ASSERT(tup != 0);
2713 tuple_for_each<I-1,Tuple>::print(os, tup, key_to_print);
2714 std::get<I-1>(*static_cast<Tuple const *>(tup)).print(os, key_to_print);
2715 }
2716 };
2717
2718 template <class Tuple>
2719 struct tuple_for_each<0, Tuple>
2720 {
2721 BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { }
2722 BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { }
2723 BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { }
2724 BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { }
2725 static void print( std::ostream &, void const *, int ) { }
2726 };
2727 }
2728
2729 ////////////////////////////////////////////
2730
2731 #if BOOST_LEAF_DIAGNOSTICS
2732
2733 namespace leaf_detail
2734 {
2735 template <class T> struct requires_unexpected { constexpr static bool value = false; };
2736 template <class T> struct requires_unexpected<T const> { constexpr static bool value = requires_unexpected<T>::value; };
2737 template <class T> struct requires_unexpected<T const &> { constexpr static bool value = requires_unexpected<T>::value; };
2738 template <class T> struct requires_unexpected<T const *> { constexpr static bool value = requires_unexpected<T>::value; };
2739 template <> struct requires_unexpected<e_unexpected_count> { constexpr static bool value = true; };
2740 template <> struct requires_unexpected<e_unexpected_info> { constexpr static bool value = true; };
2741
2742 template <class L>
2743 struct unexpected_requested;
2744
2745 template <template <class ...> class L>
2746 struct unexpected_requested<L<>>
2747 {
2748 constexpr static bool value = false;
2749 };
2750
2751 template <template <class...> class L, template <class> class S, class Car, class... Cdr>
2752 struct unexpected_requested<L<S<Car>, S<Cdr>...>>
2753 {
2754 constexpr static bool value = requires_unexpected<Car>::value || unexpected_requested<L<S<Cdr>...>>::value;
2755 };
2756 }
2757
2758 #endif
2759
2760 ////////////////////////////////////////////
2761
2762 namespace leaf_detail
2763 {
2764 template <class T> struct does_not_participate_in_context_deduction: std::false_type { };
2765 template <> struct does_not_participate_in_context_deduction<void>: std::true_type { };
2766
2767 template <class L>
2768 struct deduce_e_type_list;
2769
2770 template <template<class...> class L, class... T>
2771 struct deduce_e_type_list<L<T...>>
2772 {
2773 using type =
2774 leaf_detail_mp11::mp_remove_if<
2775 leaf_detail_mp11::mp_unique<
2776 leaf_detail_mp11::mp_list<typename handler_argument_traits<T>::error_type...>
2777 >,
2778 does_not_participate_in_context_deduction
2779 >;
2780 };
2781
2782 template <class L>
2783 struct deduce_e_tuple_impl;
2784
2785 template <template <class...> class L, class... E>
2786 struct deduce_e_tuple_impl<L<E...>>
2787 {
2788 using type = std::tuple<slot<E>...>;
2789 };
2790
2791 template <class... E>
2792 using deduce_e_tuple = typename deduce_e_tuple_impl<typename deduce_e_type_list<leaf_detail_mp11::mp_list<E...>>::type>::type;
2793 }
2794
2795 ////////////////////////////////////////////
2796
2797 template <class... E>
2798 class context
2799 {
2800 context( context const & ) = delete;
2801 context & operator=( context const & ) = delete;
2802
2803 using Tup = leaf_detail::deduce_e_tuple<E...>;
2804 Tup tup_;
2805
2806 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
2807 std::thread::id thread_id_;
2808 #endif
2809 bool is_active_;
2810
2811 protected:
2812
2813 BOOST_LEAF_CONSTEXPR error_id propagate_captured_errors( error_id err_id ) noexcept
2814 {
2815 leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate_captured(tup_, err_id.value());
2816 return err_id;
2817 }
2818
2819 public:
2820
2821 BOOST_LEAF_CONSTEXPR context( context && x ) noexcept:
2822 tup_(std::move(x.tup_)),
2823 is_active_(false)
2824 {
2825 BOOST_LEAF_ASSERT(!x.is_active());
2826 }
2827
2828 BOOST_LEAF_CONSTEXPR context() noexcept:
2829 is_active_(false)
2830 {
2831 }
2832
2833 ~context() noexcept
2834 {
2835 BOOST_LEAF_ASSERT(!is_active());
2836 }
2837
2838 BOOST_LEAF_CONSTEXPR Tup const & tup() const noexcept
2839 {
2840 return tup_;
2841 }
2842
2843 BOOST_LEAF_CONSTEXPR Tup & tup() noexcept
2844 {
2845 return tup_;
2846 }
2847
2848 BOOST_LEAF_CONSTEXPR void activate() noexcept
2849 {
2850 using namespace leaf_detail;
2851 BOOST_LEAF_ASSERT(!is_active());
2852 tuple_for_each<std::tuple_size<Tup>::value,Tup>::activate(tup_);
2853 #if BOOST_LEAF_DIAGNOSTICS
2854 if( unexpected_requested<Tup>::value )
2855 ++tl_unexpected_enabled<>::counter;
2856 #endif
2857 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
2858 thread_id_ = std::this_thread::get_id();
2859 #endif
2860 is_active_ = true;
2861 }
2862
2863 BOOST_LEAF_CONSTEXPR void deactivate() noexcept
2864 {
2865 using namespace leaf_detail;
2866 BOOST_LEAF_ASSERT(is_active());
2867 is_active_ = false;
2868 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
2869 BOOST_LEAF_ASSERT(std::this_thread::get_id() == thread_id_);
2870 thread_id_ = std::thread::id();
2871 #endif
2872 #if BOOST_LEAF_DIAGNOSTICS
2873 if( unexpected_requested<Tup>::value )
2874 --tl_unexpected_enabled<>::counter;
2875 #endif
2876 tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_);
2877 }
2878
2879 BOOST_LEAF_CONSTEXPR void propagate() noexcept
2880 {
2881 leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_);
2882 }
2883
2884 BOOST_LEAF_CONSTEXPR bool is_active() const noexcept
2885 {
2886 return is_active_;
2887 }
2888
2889 void print( std::ostream & os ) const
2890 {
2891 leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::print(os, &tup_, 0);
2892 }
2893
2894 template <class R, class... H>
2895 BOOST_LEAF_CONSTEXPR R handle_error( error_id, H && ... ) const;
2896
2897 template <class R, class... H>
2898 BOOST_LEAF_CONSTEXPR R handle_error( error_id, H && ... );
2899 };
2900
2901 ////////////////////////////////////////
2902
2903 namespace leaf_detail
2904 {
2905 template <class TypeList>
2906 struct deduce_context_impl;
2907
2908 template <template <class...> class L, class... E>
2909 struct deduce_context_impl<L<E...>>
2910 {
2911 using type = context<E...>;
2912 };
2913
2914 template <class TypeList>
2915 using deduce_context = typename deduce_context_impl<TypeList>::type;
2916
2917 template <class H>
2918 struct fn_mp_args_fwd
2919 {
2920 using type = fn_mp_args<H>;
2921 };
2922
2923 template <class... H>
2924 struct fn_mp_args_fwd<std::tuple<H...> &>: fn_mp_args_fwd<std::tuple<H...>> { };
2925
2926 template <class... H>
2927 struct fn_mp_args_fwd<std::tuple<H...>>
2928 {
2929 using type = leaf_detail_mp11::mp_append<typename fn_mp_args_fwd<H>::type...>;
2930 };
2931
2932 template <class... H>
2933 struct context_type_from_handlers_impl
2934 {
2935 using type = deduce_context<leaf_detail_mp11::mp_append<typename fn_mp_args_fwd<H>::type...>>;
2936 };
2937
2938 template <class Ctx>
2939 struct polymorphic_context_impl: polymorphic_context, Ctx
2940 {
2941 error_id propagate_captured_errors() noexcept final override { return Ctx::propagate_captured_errors(captured_id_); }
2942 void activate() noexcept final override { Ctx::activate(); }
2943 void deactivate() noexcept final override { Ctx::deactivate(); }
2944 void propagate() noexcept final override { Ctx::propagate(); }
2945 bool is_active() const noexcept final override { return Ctx::is_active(); }
2946 void print( std::ostream & os ) const final override { return Ctx::print(os); }
2947 };
2948 }
2949
2950 template <class... H>
2951 using context_type_from_handlers = typename leaf_detail::context_type_from_handlers_impl<H...>::type;
2952
2953 ////////////////////////////////////////////
2954
2955 template <class... H>
2956 BOOST_LEAF_CONSTEXPR inline context_type_from_handlers<H...> make_context() noexcept
2957 {
2958 return { };
2959 }
2960
2961 template <class... H>
2962 BOOST_LEAF_CONSTEXPR inline context_type_from_handlers<H...> make_context( H && ... ) noexcept
2963 {
2964 return { };
2965 }
2966
2967 ////////////////////////////////////////////
2968
2969 template <class... H>
2970 inline context_ptr make_shared_context() noexcept
2971 {
2972 return std::make_shared<leaf_detail::polymorphic_context_impl<context_type_from_handlers<H...>>>();
2973 }
2974
2975 template <class... H>
2976 inline context_ptr make_shared_context( H && ... ) noexcept
2977 {
2978 return std::make_shared<leaf_detail::polymorphic_context_impl<context_type_from_handlers<H...>>>();
2979 }
2980
2981 } }
2982
2983 #endif
2984 // <<< #include <boost/leaf/context.hpp>
2985 #line 12 "../../include/boost/leaf/detail/all.hpp"
2986 // >>> #include <boost/leaf/handle_errors.hpp>
2987 #line 1 "boost/leaf/handle_errors.hpp"
2988 #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
2989 #define BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
2990
2991 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2992
2993 // Distributed under the Boost Software License, Version 1.0. (See accompanying
2994 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2995
2996 #ifndef BOOST_LEAF_ENABLE_WARNINGS
2997 # if defined(__clang__)
2998 # pragma clang system_header
2999 # elif (__GNUC__*100+__GNUC_MINOR__>301)
3000 # pragma GCC system_header
3001 # elif defined(_MSC_VER)
3002 # pragma warning(push,1)
3003 # endif
3004 #endif
3005
3006 // >>> #include <boost/leaf/detail/demangle.hpp>
3007 #line 1 "boost/leaf/detail/demangle.hpp"
3008 #ifndef BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
3009 #define BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
3010
3011 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
3012
3013 // Distributed under the Boost Software License, Version 1.0. (See accompanying
3014 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3015
3016 // core::demangle
3017 //
3018 // Copyright 2014 Peter Dimov
3019 // Copyright 2014 Andrey Semashev
3020 //
3021 // Distributed under the Boost Software License, Version 1.0.
3022 // See accompanying file LICENSE_1_0.txt or copy at
3023 // http://www.boost.org/LICENSE_1_0.txt
3024
3025 #ifndef BOOST_LEAF_ENABLE_WARNINGS
3026 # if defined(__clang__)
3027 # pragma clang system_header
3028 # elif (__GNUC__*100+__GNUC_MINOR__>301)
3029 # pragma GCC system_header
3030 # elif defined(_MSC_VER)
3031 # pragma warning(push,1)
3032 # endif
3033 #endif
3034
3035 #if !defined(_MSC_VER)
3036 # if defined(__has_include) && __has_include(<cxxabi.h>)
3037 # define BOOST_LEAF_HAS_CXXABI_H
3038 # endif
3039 #endif
3040
3041 #if defined( BOOST_LEAF_HAS_CXXABI_H )
3042 # include <cxxabi.h>
3043 // For some architectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library
3044 // (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement
3045 // abi::__cxa_demangle(). We detect this implementation by checking the include guard here.
3046 # if defined( __GABIXX_CXXABI_H__ )
3047 # undef BOOST_LEAF_HAS_CXXABI_H
3048 # else
3049 # include <cstddef>
3050 # endif
3051 #endif
3052
3053 namespace boost { namespace leaf {
3054
3055 namespace leaf_detail
3056 {
3057 inline char const * demangle_alloc( char const * name ) noexcept;
3058 inline void demangle_free( char const * name ) noexcept;
3059
3060 class scoped_demangled_name
3061 {
3062 private:
3063
3064 char const * m_p;
3065
3066 public:
3067
3068 explicit scoped_demangled_name( char const * name ) noexcept :
3069 m_p( demangle_alloc( name ) )
3070 {
3071 }
3072
3073 ~scoped_demangled_name() noexcept
3074 {
3075 demangle_free( m_p );
3076 }
3077
3078 char const * get() const noexcept
3079 {
3080 return m_p;
3081 }
3082
3083 scoped_demangled_name( scoped_demangled_name const& ) = delete;
3084 scoped_demangled_name& operator= ( scoped_demangled_name const& ) = delete;
3085 };
3086
3087 #if defined( BOOST_LEAF_HAS_CXXABI_H )
3088
3089 inline char const * demangle_alloc( char const * name ) noexcept
3090 {
3091 int status = 0;
3092 std::size_t size = 0;
3093 return abi::__cxa_demangle( name, NULL, &size, &status );
3094 }
3095
3096 inline void demangle_free( char const * name ) noexcept
3097 {
3098 std::free( const_cast< char* >( name ) );
3099 }
3100
3101 inline char const * demangle( char const * name )
3102 {
3103 scoped_demangled_name demangled_name( name );
3104 char const * p = demangled_name.get();
3105 if( !p )
3106 p = name;
3107 return p;
3108 }
3109
3110 #else
3111
3112 inline char const * demangle_alloc( char const * name ) noexcept
3113 {
3114 return name;
3115 }
3116
3117 inline void demangle_free( char const * ) noexcept
3118 {
3119 }
3120
3121 inline char const * demangle( char const * name )
3122 {
3123 return name;
3124 }
3125
3126 #endif
3127 }
3128
3129 } }
3130
3131 #ifdef BOOST_LEAF_HAS_CXXABI_H
3132 # undef BOOST_LEAF_HAS_CXXABI_H
3133 #endif
3134
3135 #endif
3136 // <<< #include <boost/leaf/detail/demangle.hpp>
3137 #line 21 "boost/leaf/handle_errors.hpp"
3138
3139 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3140 #endif
3141
3142 namespace boost { namespace leaf {
3143
3144 class error_info
3145 {
3146 error_info & operator=( error_info const & ) = delete;
3147
3148 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3149 static error_id unpack_error_id( std::exception const * ex ) noexcept
3150 {
3151 if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
3152 if( is_error_id(se->code()) )
3153 return leaf_detail::make_error_id(se->code().value());
3154 if( std::error_code const * ec = dynamic_cast<std::error_code const *>(ex) )
3155 if( is_error_id(*ec) )
3156 return leaf_detail::make_error_id(ec->value());
3157 if( error_id const * err_id = dynamic_cast<error_id const *>(ex) )
3158 return *err_id;
3159 return current_error();
3160 }
3161
3162 std::exception * const ex_;
3163 #endif
3164
3165 error_id const err_id_;
3166
3167 protected:
3168
3169 error_info( error_info const & ) noexcept = default;
3170
3171 template <class CharT, class Traits>
3172 void print( std::basic_ostream<CharT, Traits> & os ) const
3173 {
3174 os << "Error ID = " << err_id_.value();
3175 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3176 if( ex_ )
3177 {
3178 os <<
3179 "\nException dynamic type: " << leaf_detail::demangle(typeid(*ex_).name()) <<
3180 "\nstd::exception::what(): " << ex_->what();
3181 }
3182 #endif
3183 }
3184
3185 public:
3186
3187 BOOST_LEAF_CONSTEXPR explicit error_info( error_id id ) noexcept:
3188 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3189 ex_(0),
3190 #endif
3191 err_id_(id)
3192 {
3193 }
3194
3195 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3196 explicit error_info( std::exception * ex ) noexcept:
3197 ex_(ex),
3198 err_id_(unpack_error_id(ex_))
3199 {
3200 }
3201 #endif
3202
3203 BOOST_LEAF_CONSTEXPR error_id error() const noexcept
3204 {
3205 return err_id_;
3206 }
3207
3208 BOOST_LEAF_CONSTEXPR std::exception * exception() const noexcept
3209 {
3210 #ifdef BOOST_LEAF_NO_EXCEPTIONS
3211 return nullptr;
3212 #else
3213 return ex_;
3214 #endif
3215 }
3216
3217 template <class CharT, class Traits>
3218 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_info const & x )
3219 {
3220 os << "leaf::error_info: ";
3221 x.print(os);
3222 return os << '\n';
3223 }
3224 };
3225
3226 ////////////////////////////////////////
3227
3228 #if BOOST_LEAF_DIAGNOSTICS
3229
3230 class diagnostic_info: public error_info
3231 {
3232 leaf_detail::e_unexpected_count const * e_uc_;
3233 void const * tup_;
3234 void (*print_)( std::ostream &, void const * tup, int key_to_print );
3235
3236 protected:
3237
3238 diagnostic_info( diagnostic_info const & ) noexcept = default;
3239
3240 template <class Tup>
3241 BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
3242 error_info(ei),
3243 e_uc_(e_uc),
3244 tup_(&tup),
3245 print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
3246 {
3247 }
3248
3249 public:
3250
3251 template <class CharT, class Traits>
3252 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
3253 {
3254 os << "leaf::diagnostic_info for ";
3255 x.print(os);
3256 os << ":\n";
3257 x.print_(os, x.tup_, x.error().value());
3258 if( x.e_uc_ )
3259 x.e_uc_->print(os);
3260 return os;
3261 }
3262 };
3263
3264 namespace leaf_detail
3265 {
3266 struct diagnostic_info_: diagnostic_info
3267 {
3268 template <class Tup>
3269 BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_count const * e_uc, Tup const & tup ) noexcept:
3270 diagnostic_info(ei, e_uc, tup)
3271 {
3272 }
3273 };
3274
3275 template <>
3276 struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<e_unexpected_count>
3277 {
3278 template <class Tup>
3279 BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
3280 {
3281 return diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_count>::check(tup, ei), tup);
3282 }
3283 };
3284 }
3285
3286 #else
3287
3288 class diagnostic_info: public error_info
3289 {
3290 protected:
3291
3292 diagnostic_info( diagnostic_info const & ) noexcept = default;
3293
3294 BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei ) noexcept:
3295 error_info(ei)
3296 {
3297 }
3298
3299 public:
3300
3301 template <class CharT, class Traits>
3302 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
3303 {
3304 os <<
3305 "leaf::diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
3306 "leaf::error_info: ";
3307 x.print(os);
3308 return os << '\n';
3309 }
3310 };
3311
3312 namespace leaf_detail
3313 {
3314 struct diagnostic_info_: diagnostic_info
3315 {
3316 BOOST_LEAF_CONSTEXPR diagnostic_info_( error_info const & ei ) noexcept:
3317 diagnostic_info(ei)
3318 {
3319 }
3320 };
3321
3322 template <>
3323 struct handler_argument_traits<diagnostic_info const &>: handler_argument_always_available<void>
3324 {
3325 template <class Tup>
3326 BOOST_LEAF_CONSTEXPR static diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
3327 {
3328 return diagnostic_info_(ei);
3329 }
3330 };
3331 }
3332
3333 #endif
3334
3335 ////////////////////////////////////////
3336
3337 #if BOOST_LEAF_DIAGNOSTICS
3338
3339 class verbose_diagnostic_info: public error_info
3340 {
3341 leaf_detail::e_unexpected_info const * e_ui_;
3342 void const * tup_;
3343 void (*print_)( std::ostream &, void const * tup, int key_to_print );
3344
3345 protected:
3346
3347 verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
3348
3349 template <class Tup>
3350 BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
3351 error_info(ei),
3352 e_ui_(e_ui),
3353 tup_(&tup),
3354 print_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
3355 {
3356 }
3357
3358 public:
3359
3360 template <class CharT, class Traits>
3361 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
3362 {
3363 os << "leaf::verbose_diagnostic_info for ";
3364 x.print(os);
3365 os << ":\n";
3366 x.print_(os, x.tup_, x.error().value());
3367 if( x.e_ui_ )
3368 x.e_ui_->print(os);
3369 return os;
3370 }
3371 };
3372
3373 namespace leaf_detail
3374 {
3375 struct verbose_diagnostic_info_: verbose_diagnostic_info
3376 {
3377 template <class Tup>
3378 BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei, leaf_detail::e_unexpected_info const * e_ui, Tup const & tup ) noexcept:
3379 verbose_diagnostic_info(ei, e_ui, tup)
3380 {
3381 }
3382 };
3383
3384 template <>
3385 struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<e_unexpected_info>
3386 {
3387 template <class Tup>
3388 BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
3389 {
3390 return verbose_diagnostic_info_(ei, handler_argument_traits_defaults<e_unexpected_info>::check(tup, ei), tup);
3391 }
3392 };
3393 }
3394
3395 #else
3396
3397 class verbose_diagnostic_info: public error_info
3398 {
3399 protected:
3400
3401 verbose_diagnostic_info( verbose_diagnostic_info const & ) noexcept = default;
3402
3403 BOOST_LEAF_CONSTEXPR verbose_diagnostic_info( error_info const & ei ) noexcept:
3404 error_info(ei)
3405 {
3406 }
3407
3408 public:
3409
3410 template <class CharT, class Traits>
3411 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, verbose_diagnostic_info const & x )
3412 {
3413 os <<
3414 "leaf::verbose_diagnostic_info requires #define BOOST_LEAF_DIAGNOSTICS 1\n"
3415 "leaf::error_info: ";
3416 x.print(os);
3417 return os << '\n';
3418 }
3419 };
3420
3421 namespace leaf_detail
3422 {
3423 struct verbose_diagnostic_info_: verbose_diagnostic_info
3424 {
3425 BOOST_LEAF_CONSTEXPR verbose_diagnostic_info_( error_info const & ei ) noexcept:
3426 verbose_diagnostic_info(ei)
3427 {
3428 }
3429 };
3430
3431
3432 template <>
3433 struct handler_argument_traits<verbose_diagnostic_info const &>: handler_argument_always_available<void>
3434 {
3435 template <class Tup>
3436 BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
3437 {
3438 return verbose_diagnostic_info_(ei);
3439 }
3440 };
3441 }
3442
3443 #endif
3444
3445 ////////////////////////////////////////
3446
3447 namespace leaf_detail
3448 {
3449 template <class T, class... List>
3450 struct type_index;
3451
3452 template <class T, class... Cdr>
3453 struct type_index<T, T, Cdr...>
3454 {
3455 constexpr static int value = 0;
3456 };
3457
3458 template <class T, class Car, class... Cdr>
3459 struct type_index<T, Car, Cdr...>
3460 {
3461 constexpr static int value = 1 + type_index<T,Cdr...>::value;
3462 };
3463
3464 template <class T, class Tuple>
3465 struct tuple_type_index;
3466
3467 template <class T, class... TupleTypes>
3468 struct tuple_type_index<T,std::tuple<TupleTypes...>>
3469 {
3470 constexpr static int value = type_index<T,TupleTypes...>::value;
3471 };
3472
3473 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3474
3475 template <class E, bool = std::is_class<E>::value>
3476 struct peek_exception;
3477
3478 template <>
3479 struct peek_exception<std::exception const, true>
3480 {
3481 BOOST_LEAF_CONSTEXPR static std::exception const * peek( error_info const & ei ) noexcept
3482 {
3483 return ei.exception();
3484 }
3485 };
3486
3487 template <>
3488 struct peek_exception<std::exception, true>
3489 {
3490 BOOST_LEAF_CONSTEXPR static std::exception * peek( error_info const & ei ) noexcept
3491 {
3492 return ei.exception();
3493 }
3494 };
3495
3496 template <>
3497 struct peek_exception<std::error_code const, true>
3498 {
3499 static std::error_code const * peek( error_info const & ei ) noexcept
3500 {
3501 auto const ex = ei.exception();
3502 if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
3503 return &se->code();
3504 else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
3505 return ec;
3506 else
3507 return 0;
3508 }
3509 };
3510
3511 template <>
3512 struct peek_exception<std::error_code, true>
3513 {
3514 static std::error_code * peek( error_info const & ei ) noexcept
3515 {
3516 auto const ex = ei.exception();
3517 if( std::system_error * se = dynamic_cast<std::system_error *>(ex) )
3518 return const_cast<std::error_code *>(&se->code());
3519 else if( std::error_code * ec = dynamic_cast<std::error_code *>(ex) )
3520 return ec;
3521 else
3522 return 0;
3523 }
3524 };
3525
3526 template <class E>
3527 struct peek_exception<E, true>
3528 {
3529 static E * peek( error_info const & ei ) noexcept
3530 {
3531 return dynamic_cast<E *>(ei.exception());
3532 }
3533 };
3534
3535 template <class E>
3536 struct peek_exception<E, false>
3537 {
3538 BOOST_LEAF_CONSTEXPR static E * peek( error_info const & ) noexcept
3539 {
3540 return 0;
3541 }
3542 };
3543
3544 #endif
3545
3546 template <class E, class SlotsTuple>
3547 BOOST_LEAF_CONSTEXPR inline
3548 E const *
3549 peek( SlotsTuple const & tup, error_info const & ei ) noexcept
3550 {
3551 if( error_id err = ei.error() )
3552 if( E const * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
3553 return e;
3554 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3555 else
3556 return peek_exception<E const>::peek(ei);
3557 #endif
3558 return 0;
3559 }
3560
3561 template <class E, class SlotsTuple>
3562 BOOST_LEAF_CONSTEXPR inline
3563 E *
3564 peek( SlotsTuple & tup, error_info const & ei ) noexcept
3565 {
3566 if( error_id err = ei.error() )
3567 if( E * e = std::get<tuple_type_index<slot<E>,SlotsTuple>::value>(tup).has_value(err.value()) )
3568 return e;
3569 #ifndef BOOST_LEAF_NO_EXCEPTIONS
3570 else
3571 return peek_exception<E>::peek(ei);
3572 #endif
3573 return 0;
3574 }
3575 }
3576
3577 ////////////////////////////////////////
3578
3579 namespace leaf_detail
3580 {
3581 template <class A>
3582 template <class Tup>
3583 BOOST_LEAF_CONSTEXPR inline
3584 typename handler_argument_traits_defaults<A, false>::error_type const *
3585 handler_argument_traits_defaults<A, false>::
3586 check( Tup const & tup, error_info const & ei ) noexcept
3587 {
3588 return peek<typename std::decay<A>::type>(tup, ei);
3589 }
3590
3591 template <class A>
3592 template <class Tup>
3593 BOOST_LEAF_CONSTEXPR inline
3594 typename handler_argument_traits_defaults<A, false>::error_type *
3595 handler_argument_traits_defaults<A, false>::
3596 check( Tup & tup, error_info const & ei ) noexcept
3597 {
3598 return peek<typename std::decay<A>::type>(tup, ei);
3599 }
3600
3601 template <class Tup>
3602 BOOST_LEAF_CONSTEXPR inline
3603 std::exception const *
3604 handler_argument_traits<void>::
3605 check( Tup const &, error_info const & ei ) noexcept
3606 {
3607 return ei.exception();
3608 }
3609
3610 template <class Tup, class... List>
3611 struct check_arguments;
3612
3613 template <class Tup>
3614 struct check_arguments<Tup>
3615 {
3616 BOOST_LEAF_CONSTEXPR static bool check( Tup const &, error_info const & )
3617 {
3618 return true;
3619 }
3620 };
3621
3622 template <class Tup, class Car, class... Cdr>
3623 struct check_arguments<Tup, Car, Cdr...>
3624 {
3625 BOOST_LEAF_CONSTEXPR static bool check( Tup & tup, error_info const & ei ) noexcept
3626 {
3627 return handler_argument_traits<Car>::check(tup, ei) && check_arguments<Tup, Cdr...>::check(tup, ei);
3628 }
3629 };
3630 }
3631
3632 ////////////////////////////////////////
3633
3634 namespace leaf_detail
3635 {
3636 template <class>
3637 struct handler_matches_any_error: std::false_type
3638 {
3639 };
3640
3641 template <template<class...> class L>
3642 struct handler_matches_any_error<L<>>: std::true_type
3643 {
3644 };
3645
3646 template <template<class...> class L, class Car, class... Cdr>
3647 struct handler_matches_any_error<L<Car, Cdr...>>
3648 {
3649 constexpr static bool value = handler_argument_traits<Car>::always_available && handler_matches_any_error<L<Cdr...>>::value;
3650 };
3651 }
3652
3653 ////////////////////////////////////////
3654
3655 namespace leaf_detail
3656 {
3657 template <class Tup, class... A>
3658 BOOST_LEAF_CONSTEXPR inline bool check_handler_( Tup & tup, error_info const & ei, leaf_detail_mp11::mp_list<A...> ) noexcept
3659 {
3660 return check_arguments<Tup, A...>::check(tup, ei);
3661 }
3662
3663 template <class R, class F, bool IsResult = is_result_type<R>::value, class FReturnType = fn_return_type<F>>
3664 struct handler_caller
3665 {
3666 template <class Tup, class... A>
3667 BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
3668 {
3669 return std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
3670 }
3671 };
3672
3673 template <template <class...> class Result, class... E, class F>
3674 struct handler_caller<Result<void, E...>, F, true, void>
3675 {
3676 using R = Result<void, E...>;
3677
3678 template <class Tup, class... A>
3679 BOOST_LEAF_CONSTEXPR static R call( Tup & tup, error_info const & ei, F && f, leaf_detail_mp11::mp_list<A...> )
3680 {
3681 std::forward<F>(f)( handler_argument_traits<A>::get(tup, ei)... );
3682 return { };
3683 }
3684 };
3685
3686 template <class T>
3687 struct is_tuple: std::false_type { };
3688
3689 template <class... T>
3690 struct is_tuple<std::tuple<T...>>: std::true_type { };
3691
3692 template <class... T>
3693 struct is_tuple<std::tuple<T...> &>: std::true_type { };
3694
3695 template <class R, class Tup, class H>
3696 BOOST_LEAF_CONSTEXPR
3697 inline
3698 typename std::enable_if<!is_tuple<H>::value, R>::type
3699 handle_error_( Tup & tup, error_info const & ei, H && h )
3700 {
3701 static_assert( handler_matches_any_error<fn_mp_args<H>>::value, "The last handler passed to handle_all must match any error." );
3702 return handler_caller<R, H>::call( tup, ei, std::forward<H>(h), fn_mp_args<H>{ } );
3703 }
3704
3705 template <class R, class Tup, class Car, class... Cdr>
3706 BOOST_LEAF_CONSTEXPR inline
3707 typename std::enable_if<!is_tuple<Car>::value, R>::type
3708 handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
3709 {
3710 if( handler_matches_any_error<fn_mp_args<Car>>::value || check_handler_( tup, ei, fn_mp_args<Car>{ } ) )
3711 return handler_caller<R, Car>::call( tup, ei, std::forward<Car>(car), fn_mp_args<Car>{ } );
3712 else
3713 return handle_error_<R>( tup, ei, std::forward<Cdr>(cdr)...);
3714 }
3715
3716 template <class R, class Tup, class HTup, size_t ... I>
3717 BOOST_LEAF_CONSTEXPR inline
3718 R
3719 handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup )
3720 {
3721 return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))...);
3722 }
3723
3724 template <class R, class Tup, class HTup, class... Cdr, size_t ... I>
3725 BOOST_LEAF_CONSTEXPR inline
3726 R
3727 handle_error_tuple_( Tup & tup, error_info const & ei, leaf_detail_mp11::index_sequence<I...>, HTup && htup, Cdr && ... cdr )
3728 {
3729 return handle_error_<R>(tup, ei, std::get<I>(std::forward<HTup>(htup))..., std::forward<Cdr>(cdr)...);
3730 }
3731
3732 template <class R, class Tup, class H>
3733 BOOST_LEAF_CONSTEXPR inline
3734 typename std::enable_if<is_tuple<H>::value, R>::type
3735 handle_error_( Tup & tup, error_info const & ei, H && h )
3736 {
3737 return handle_error_tuple_<R>(
3738 tup,
3739 ei,
3740 leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<H>::type>::value>(),
3741 std::forward<H>(h));
3742 }
3743
3744 template <class R, class Tup, class Car, class... Cdr>
3745 BOOST_LEAF_CONSTEXPR inline
3746 typename std::enable_if<is_tuple<Car>::value, R>::type
3747 handle_error_( Tup & tup, error_info const & ei, Car && car, Cdr && ... cdr )
3748 {
3749 return handle_error_tuple_<R>(
3750 tup,
3751 ei,
3752 leaf_detail_mp11::make_index_sequence<std::tuple_size<typename std::decay<Car>::type>::value>(),
3753 std::forward<Car>(car),
3754 std::forward<Cdr>(cdr)...);
3755 }
3756 }
3757
3758 ////////////////////////////////////////
3759
3760 template <class... E>
3761 template <class R, class... H>
3762 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
3763 R
3764 context<E...>::
3765 handle_error( error_id id, H && ... h ) const
3766 {
3767 BOOST_LEAF_ASSERT(!is_active());
3768 return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
3769 }
3770
3771 template <class... E>
3772 template <class R, class... H>
3773 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE
3774 R
3775 context<E...>::
3776 handle_error( error_id id, H && ... h )
3777 {
3778 BOOST_LEAF_ASSERT(!is_active());
3779 return leaf_detail::handle_error_<R>(tup(), error_info(id), std::forward<H>(h)...);
3780 }
3781
3782 ////////////////////////////////////////
3783
3784 #ifdef BOOST_LEAF_NO_EXCEPTIONS
3785
3786 template <class TryBlock, class... H>
3787 BOOST_LEAF_CONSTEXPR inline
3788 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
3789 try_handle_all( TryBlock && try_block, H && ... h ) noexcept
3790 {
3791 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");
3792 context_type_from_handlers<H...> ctx;
3793 auto active_context = activate_context(ctx);
3794 if( auto r = std::forward<TryBlock>(try_block)() )
3795 return r.value();
3796 else
3797 {
3798 error_id id = r.error();
3799 ctx.deactivate();
3800 using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
3801 return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
3802 }
3803 }
3804
3805 template <class TryBlock, class... H>
3806 BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
3807 typename std::decay<decltype(std::declval<TryBlock>()())>::type
3808 try_handle_some( TryBlock && try_block, H && ... h ) noexcept
3809 {
3810 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");
3811 context_type_from_handlers<H...> ctx;
3812 auto active_context = activate_context(ctx);
3813 if( auto r = std::forward<TryBlock>(try_block)() )
3814 return r;
3815 else
3816 {
3817 error_id id = r.error();
3818 ctx.deactivate();
3819 using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
3820 auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
3821 if( !rr )
3822 ctx.propagate();
3823 return rr;
3824 }
3825 }
3826
3827 template <class TryBlock, class... H>
3828 BOOST_LEAF_CONSTEXPR inline
3829 decltype(std::declval<TryBlock>()())
3830 try_catch( TryBlock && try_block, H && ... ) noexcept
3831 {
3832 static_assert(sizeof(context_type_from_handlers<H...>) > 0,
3833 "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.");
3834 return std::forward<TryBlock>(try_block)();
3835 }
3836
3837 #else
3838
3839 namespace leaf_detail
3840 {
3841 template <class Ctx, class TryBlock, class... H>
3842 decltype(std::declval<TryBlock>()())
3843 try_catch_( Ctx & ctx, TryBlock && try_block, H && ... h )
3844 {
3845 using namespace leaf_detail;
3846 BOOST_LEAF_ASSERT(ctx.is_active());
3847 using R = decltype(std::declval<TryBlock>()());
3848 try
3849 {
3850 return std::forward<TryBlock>(try_block)();
3851 }
3852 catch( capturing_exception const & cap )
3853 {
3854 try
3855 {
3856 cap.unload_and_rethrow_original_exception();
3857 }
3858 catch( std::exception & ex )
3859 {
3860 ctx.deactivate();
3861 return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
3862 []() -> R { throw; } );
3863 }
3864 catch(...)
3865 {
3866 ctx.deactivate();
3867 return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
3868 []() -> R { throw; } );
3869 }
3870 }
3871 catch( std::exception & ex )
3872 {
3873 ctx.deactivate();
3874 return handle_error_<R>(ctx.tup(), error_info(&ex), std::forward<H>(h)...,
3875 []() -> R { throw; } );
3876 }
3877 catch(...)
3878 {
3879 ctx.deactivate();
3880 return handle_error_<R>(ctx.tup(), error_info(nullptr), std::forward<H>(h)...,
3881 []() -> R { throw; } );
3882 }
3883 }
3884 }
3885
3886 template <class TryBlock, class... H>
3887 BOOST_LEAF_CONSTEXPR inline
3888 typename std::decay<decltype(std::declval<TryBlock>()().value())>::type
3889 try_handle_all( TryBlock && try_block, H && ... h )
3890 {
3891 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");
3892 context_type_from_handlers<H...> ctx;
3893 auto active_context = activate_context(ctx);
3894 if( auto r = leaf_detail::try_catch_(
3895 ctx,
3896 [&]
3897 {
3898 return std::forward<TryBlock>(try_block)();
3899 },
3900 std::forward<H>(h)...) )
3901 return r.value();
3902 else
3903 {
3904 error_id id = r.error();
3905 if( ctx.is_active() )
3906 ctx.deactivate();
3907 using R = typename std::decay<decltype(std::declval<TryBlock>()().value())>::type;
3908 return ctx.template handle_error<R>(std::move(id), std::forward<H>(h)...);
3909 }
3910 }
3911
3912 template <class TryBlock, class... H>
3913 BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline
3914 typename std::decay<decltype(std::declval<TryBlock>()())>::type
3915 try_handle_some( TryBlock && try_block, H && ... h )
3916 {
3917 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");
3918 context_type_from_handlers<H...> ctx;
3919 auto active_context = activate_context(ctx);
3920 if( auto r = leaf_detail::try_catch_(
3921 ctx,
3922 [&]
3923 {
3924 return std::forward<TryBlock>(try_block)();
3925 },
3926 std::forward<H>(h)...) )
3927 return r;
3928 else
3929 {
3930 error_id id = r.error();
3931 if( ctx.is_active() )
3932 ctx.deactivate();
3933 using R = typename std::decay<decltype(std::declval<TryBlock>()())>::type;
3934 auto rr = ctx.template handle_error<R>(std::move(id), std::forward<H>(h)..., [&r]()->R { return std::move(r); });
3935 if( !rr )
3936 ctx.propagate();
3937 return rr;
3938 }
3939 }
3940
3941 template <class TryBlock, class... H>
3942 BOOST_LEAF_CONSTEXPR inline
3943 decltype(std::declval<TryBlock>()())
3944 try_catch( TryBlock && try_block, H && ... h )
3945 {
3946 context_type_from_handlers<H...> ctx;
3947 auto active_context = activate_context(ctx);
3948 return leaf_detail::try_catch_(
3949 ctx,
3950 [&]
3951 {
3952 return std::forward<TryBlock>(try_block)();
3953 },
3954 std::forward<H>(h)...);
3955 }
3956
3957 #endif
3958
3959 } }
3960
3961 // Boost Exception Integration
3962
3963 namespace boost { class exception; }
3964 namespace boost { template <class Tag,class T> class error_info; }
3965 namespace boost { namespace exception_detail { template <class ErrorInfo> struct get_info; } }
3966
3967 namespace boost { namespace leaf {
3968
3969 namespace leaf_detail
3970 {
3971 template <class T>
3972 struct match_enum_type;
3973
3974 template <class Tag, class T>
3975 struct match_enum_type<boost::error_info<Tag, T>>
3976 {
3977 using type = T;
3978 };
3979
3980 template <class Ex>
3981 BOOST_LEAF_CONSTEXPR inline Ex * get_exception( error_info const & ei )
3982 {
3983 return dynamic_cast<Ex *>(ei.exception());
3984 }
3985
3986 template <class, class T>
3987 struct dependent_type { using type = T; };
3988
3989 template <class Dep, class T>
3990 using dependent_type_t = typename dependent_type<Dep, T>::type;
3991
3992 template <class Tag, class T>
3993 struct handler_argument_traits<boost::error_info<Tag, T>>
3994 {
3995 using error_type = void;
3996 constexpr static bool always_available = false;
3997
3998 template <class Tup>
3999 BOOST_LEAF_CONSTEXPR static T * check( Tup & tup, error_info const & ei ) noexcept
4000 {
4001 using boost_exception = dependent_type_t<T, boost::exception>;
4002 if( auto * be = get_exception<boost_exception>(ei) )
4003 return exception_detail::get_info<boost::error_info<Tag, T>>::get(*be);
4004 else
4005 return 0;
4006 }
4007
4008 template <class Tup>
4009 BOOST_LEAF_CONSTEXPR static boost::error_info<Tag, T> get( Tup const & tup, error_info const & ei ) noexcept
4010 {
4011 return boost::error_info<Tag, T>(*check(tup, ei));
4012 }
4013 };
4014
4015 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>> { };
4016 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>> { };
4017 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>> { };
4018 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>> { };
4019 }
4020
4021 } }
4022
4023 #endif
4024 // <<< #include <boost/leaf/handle_errors.hpp>
4025 #line 15 "../../include/boost/leaf/detail/all.hpp"
4026 // >>> #include <boost/leaf/pred.hpp>
4027 #line 1 "boost/leaf/pred.hpp"
4028 #ifndef BOOST_LEAF_PRED_HPP_INCLUDED
4029 #define BOOST_LEAF_PRED_HPP_INCLUDED
4030
4031 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
4032
4033 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4034 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4035
4036 #ifndef BOOST_LEAF_ENABLE_WARNINGS
4037 # if defined(__clang__)
4038 # pragma clang system_header
4039 # elif (__GNUC__*100+__GNUC_MINOR__>301)
4040 # pragma GCC system_header
4041 # elif defined(_MSC_VER)
4042 # pragma warning(push,1)
4043 # endif
4044 #endif
4045
4046
4047 #if __cplusplus >= 201703L
4048 # define BOOST_LEAF_MATCH_ARGS(et,v1,v) auto v1, auto... v
4049 #else
4050 # define BOOST_LEAF_MATCH_ARGS(et,v1,v) typename leaf_detail::et::type v1, typename leaf_detail::et::type... v
4051 #endif
4052 #define BOOST_LEAF_ESC(...) __VA_ARGS__
4053
4054 namespace boost { namespace leaf {
4055
4056 namespace leaf_detail
4057 {
4058 #if __cplusplus >= 201703L
4059 template <class MatchType, class T>
4060 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) noexcept ) noexcept
4061 {
4062 BOOST_LEAF_ASSERT(P != 0);
4063 return P(e);
4064 }
4065
4066 template <class MatchType, class T>
4067 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) )
4068 {
4069 BOOST_LEAF_ASSERT(P != 0);
4070 return P(e);
4071 }
4072 #endif
4073
4074 template <class MatchType, class V>
4075 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, V v )
4076 {
4077 return e == v;
4078 }
4079
4080 template <class MatchType, class VCar, class... VCdr>
4081 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, VCar car, VCdr ... cdr )
4082 {
4083 return cmp_value_pack(e, car) || cmp_value_pack(e, cdr...);
4084 }
4085 }
4086
4087 ////////////////////////////////////////
4088
4089 template <class E, class Enum = E>
4090 struct condition
4091 {
4092 static_assert(std::is_error_condition_enum<Enum>::value || std::is_error_code_enum<Enum>::value, "leaf::condition<E, Enum> requires Enum to be registered either with std::is_error_condition_enum or std::is_error_code_enum.");
4093 };
4094
4095 template <class Enum>
4096 struct condition<Enum, Enum>
4097 {
4098 static_assert(std::is_error_condition_enum<Enum>::value || std::is_error_code_enum<Enum>::value, "leaf::condition<Enum> requires Enum to be registered either with std::is_error_condition_enum or std::is_error_code_enum.");
4099 };
4100
4101 #if __cplusplus >= 201703L
4102 template <class ErrorCodeEnum>
4103 BOOST_LEAF_CONSTEXPR inline bool category( std::error_code const & ec )
4104 {
4105 static_assert(std::is_error_code_enum<ErrorCodeEnum>::value, "leaf::category requires an error code enum");
4106 return &ec.category() == &std::error_code(ErrorCodeEnum{}).category();
4107 }
4108 #endif
4109
4110 ////////////////////////////////////////
4111
4112 namespace leaf_detail
4113 {
4114 template <class T>
4115 struct match_enum_type
4116 {
4117 using type = T;
4118 };
4119
4120 template <class Enum>
4121 struct match_enum_type<condition<Enum, Enum>>
4122 {
4123 using type = Enum;
4124 };
4125
4126 template <class E, class Enum>
4127 struct match_enum_type<condition<E, Enum>>
4128 {
4129 static_assert(sizeof(Enum) == 0, "leaf::condition<E, Enum> should be used with leaf::match_value<>, not with leaf::match<>");
4130 };
4131 }
4132
4133 template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
4134 struct match
4135 {
4136 using error_type = E;
4137 E matched;
4138
4139 template <class T>
4140 BOOST_LEAF_CONSTEXPR static bool evaluate(T && x)
4141 {
4142 return leaf_detail::cmp_value_pack(std::forward<T>(x), V1, V...);
4143 }
4144 };
4145
4146 template <class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_enum_type<condition<Enum, Enum>>), V1, V)>
4147 struct match<condition<Enum, Enum>, V1, V...>
4148 {
4149 using error_type = std::error_code;
4150 std::error_code const & matched;
4151
4152 BOOST_LEAF_CONSTEXPR static bool evaluate(std::error_code const & e) noexcept
4153 {
4154 return leaf_detail::cmp_value_pack(e, V1, V...);
4155 }
4156 };
4157
4158 template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
4159 struct is_predicate<match<E, V1, V...>>: std::true_type
4160 {
4161 };
4162
4163 ////////////////////////////////////////
4164
4165 namespace leaf_detail
4166 {
4167 template <class E>
4168 struct match_value_enum_type
4169 {
4170 using type = typename std::remove_reference<decltype(std::declval<E>().value)>::type;
4171 };
4172
4173 template <class E, class Enum>
4174 struct match_value_enum_type<condition<E, Enum>>
4175 {
4176 using type = Enum;
4177 };
4178
4179 template <class Enum>
4180 struct match_value_enum_type<condition<Enum, Enum>>
4181 {
4182 static_assert(sizeof(Enum)==0, "leaf::condition<Enum> should be used with leaf::match<>, not with leaf::match_value<>");
4183 };
4184 }
4185
4186 template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
4187 struct match_value
4188 {
4189 using error_type = E;
4190 E const & matched;
4191
4192 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
4193 {
4194 return leaf_detail::cmp_value_pack(e.value, V1, V...);
4195 }
4196 };
4197
4198 template <class E, class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_value_enum_type<condition<E, Enum>>), V1, V)>
4199 struct match_value<condition<E, Enum>, V1, V...>
4200 {
4201 using error_type = E;
4202 E const & matched;
4203
4204 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e)
4205 {
4206 return leaf_detail::cmp_value_pack(e.value, V1, V...);
4207 }
4208 };
4209
4210 template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
4211 struct is_predicate<match_value<E, V1, V...>>: std::true_type
4212 {
4213 };
4214
4215 ////////////////////////////////////////
4216
4217 #if __cplusplus >= 201703L
4218 template <auto, auto, auto...>
4219 struct match_member;
4220
4221 template <class T, class E, T E::* P, auto V1, auto... V>
4222 struct match_member<P, V1, V...>
4223 {
4224 using error_type = E;
4225 E const & matched;
4226
4227 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
4228 {
4229 return leaf_detail::cmp_value_pack(e.*P, V1, V...);
4230 }
4231 };
4232
4233 template <auto P, auto V1, auto... V>
4234 struct is_predicate<match_member<P, V1, V...>>: std::true_type
4235 {
4236 };
4237 #endif
4238
4239 ////////////////////////////////////////
4240
4241 template <class P>
4242 struct if_not
4243 {
4244 using error_type = typename P::error_type;;
4245 decltype(std::declval<P>().matched) matched;
4246
4247 template <class E>
4248 BOOST_LEAF_CONSTEXPR static bool evaluate(E && e) noexcept
4249 {
4250 return !P::evaluate(std::forward<E>(e));
4251 }
4252 };
4253
4254 template <class P>
4255 struct is_predicate<if_not<P>>: std::true_type
4256 {
4257 };
4258
4259 ////////////////////////////////////////
4260
4261
4262 #ifndef BOOST_LEAF_NO_EXCEPTIONS
4263
4264 namespace leaf_detail
4265 {
4266 template <class Ex>
4267 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const * ) noexcept
4268 {
4269 return dynamic_cast<Ex const *>(&ex)!=0;
4270 }
4271
4272 template <class Ex, class... ExRest>
4273 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const *, ExRest const * ... ex_rest ) noexcept
4274 {
4275 return dynamic_cast<Ex const *>(&ex)!=0 || check_exception_pack(ex, ex_rest...);
4276 }
4277
4278 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ) noexcept
4279 {
4280 return true;
4281 }
4282 }
4283
4284 template <class... Ex>
4285 struct catch_
4286 {
4287 using error_type = void;
4288 std::exception const & matched;
4289
4290 BOOST_LEAF_CONSTEXPR static bool evaluate(std::exception const & ex) noexcept
4291 {
4292 return leaf_detail::check_exception_pack(ex, static_cast<Ex const *>(0)...);
4293 }
4294 };
4295
4296 template <class Ex>
4297 struct catch_<Ex>
4298 {
4299 using error_type = void;
4300 Ex const & matched;
4301
4302 BOOST_LEAF_CONSTEXPR static Ex const * evaluate(std::exception const & ex) noexcept
4303 {
4304 return dynamic_cast<Ex const *>(&ex);
4305 }
4306
4307 explicit catch_( std::exception const & ex ):
4308 matched(*dynamic_cast<Ex const *>(&ex))
4309 {
4310 }
4311 };
4312
4313 template <class... Ex>
4314 struct is_predicate<catch_<Ex...>>: std::true_type
4315 {
4316 };
4317
4318 #endif
4319
4320 } }
4321
4322 #endif
4323 // <<< #include <boost/leaf/pred.hpp>
4324 #line 17 "../../include/boost/leaf/detail/all.hpp"
4325 // >>> #include <boost/leaf/result.hpp>
4326 #line 1 "boost/leaf/result.hpp"
4327 #ifndef BOOST_LEAF_RESULT_HPP_INCLUDED
4328 #define BOOST_LEAF_RESULT_HPP_INCLUDED
4329
4330 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
4331
4332 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4333 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4334
4335 #ifndef BOOST_LEAF_ENABLE_WARNINGS
4336 # if defined(__clang__)
4337 # pragma clang system_header
4338 # elif (__GNUC__*100+__GNUC_MINOR__>301)
4339 # pragma GCC system_header
4340 # elif defined(_MSC_VER)
4341 # pragma warning(push,1)
4342 # endif
4343 #endif
4344
4345 #include <climits>
4346
4347 namespace boost { namespace leaf {
4348
4349 class bad_result:
4350 public std::exception,
4351 public error_id
4352 {
4353 char const * what() const noexcept final override
4354 {
4355 return "boost::leaf::bad_result";
4356 }
4357
4358 public:
4359
4360 explicit bad_result( error_id id ) noexcept:
4361 error_id(id)
4362 {
4363 BOOST_LEAF_ASSERT(value());
4364 }
4365 };
4366
4367 ////////////////////////////////////////
4368
4369 namespace leaf_detail
4370 {
4371 template <class T>
4372 struct stored
4373 {
4374 using type = T;
4375 using value_type = T;
4376 using value_type_const = T const;
4377 using value_cref = T const &;
4378 using value_ref = T &;
4379 using value_rv_cref = T const &&;
4380 using value_rv_ref = T &&;
4381 };
4382
4383 template <class T>
4384 struct stored<T &>
4385 {
4386 using type = std::reference_wrapper<T>;
4387 using value_type_const = T;
4388 using value_type = T;
4389 using value_ref = T &;
4390 using value_cref = T &;
4391 using value_rv_ref = T &;
4392 using value_rv_cref = T &;
4393 };
4394
4395 class result_discriminant
4396 {
4397 unsigned state_;
4398
4399 public:
4400
4401 enum kind_t
4402 {
4403 no_error = 0,
4404 err_id = 1,
4405 ctx_ptr = 2,
4406 val = 3
4407 };
4408
4409 explicit result_discriminant( error_id id ) noexcept:
4410 state_(id.value())
4411 {
4412 BOOST_LEAF_ASSERT(state_==0 || (state_&3)==1);
4413 }
4414
4415 struct kind_val { };
4416 explicit result_discriminant( kind_val ) noexcept:
4417 state_(val)
4418 {
4419 }
4420
4421 struct kind_ctx_ptr { };
4422 explicit result_discriminant( kind_ctx_ptr ) noexcept:
4423 state_(ctx_ptr)
4424 {
4425 }
4426
4427 kind_t kind() const noexcept
4428 {
4429 return kind_t(state_&3);
4430 }
4431
4432 error_id get_error_id() const noexcept
4433 {
4434 BOOST_LEAF_ASSERT(kind()==no_error || kind()==err_id);
4435 return make_error_id(state_);
4436 }
4437 };
4438 }
4439
4440 ////////////////////////////////////////
4441
4442 template <class T>
4443 class result
4444 {
4445 template <class U>
4446 friend class result;
4447
4448 using result_discriminant = leaf_detail::result_discriminant;
4449
4450 struct error_result
4451 {
4452 error_result( error_result && ) = default;
4453 error_result( error_result const & ) = delete;
4454 error_result & operator=( error_result const & ) = delete;
4455
4456 result & r_;
4457
4458 error_result( result & r ) noexcept:
4459 r_(r)
4460 {
4461 }
4462
4463 template <class U>
4464 operator result<U>() noexcept
4465 {
4466 switch(r_.what_.kind())
4467 {
4468 case result_discriminant::val:
4469 return result<U>(error_id());
4470 case result_discriminant::ctx_ptr:
4471 return result<U>(std::move(r_.ctx_));
4472 default:
4473 return result<U>(std::move(r_.what_));
4474 }
4475 }
4476
4477 operator error_id() noexcept
4478 {
4479 switch(r_.what_.kind())
4480 {
4481 case result_discriminant::val:
4482 return error_id();
4483 case result_discriminant::ctx_ptr:
4484 {
4485 error_id captured_id = r_.ctx_->propagate_captured_errors();
4486 leaf_detail::id_factory<>::current_id = captured_id.value();
4487 return captured_id;
4488 }
4489 default:
4490 return r_.what_.get_error_id();
4491 }
4492 }
4493 };
4494
4495 using stored_type = typename leaf_detail::stored<T>::type;
4496 using value_type = typename leaf_detail::stored<T>::value_type;
4497 using value_type_const = typename leaf_detail::stored<T>::value_type_const;
4498 using value_ref = typename leaf_detail::stored<T>::value_ref;
4499 using value_cref = typename leaf_detail::stored<T>::value_cref;
4500 using value_rv_ref = typename leaf_detail::stored<T>::value_rv_ref;
4501 using value_rv_cref = typename leaf_detail::stored<T>::value_rv_cref;
4502
4503 union
4504 {
4505 stored_type stored_;
4506 context_ptr ctx_;
4507 };
4508
4509 result_discriminant what_;
4510
4511 void destroy() const noexcept
4512 {
4513 switch(this->what_.kind())
4514 {
4515 case result_discriminant::val:
4516 stored_.~stored_type();
4517 break;
4518 case result_discriminant::ctx_ptr:
4519 BOOST_LEAF_ASSERT(!ctx_ || ctx_->captured_id_);
4520 ctx_.~context_ptr();
4521 default:
4522 break;
4523 }
4524 }
4525
4526 template <class U>
4527 result_discriminant move_from( result<U> && x ) noexcept
4528 {
4529 auto x_what = x.what_;
4530 switch(x_what.kind())
4531 {
4532 case result_discriminant::val:
4533 (void) new(&stored_) stored_type(std::move(x.stored_));
4534 break;
4535 case result_discriminant::ctx_ptr:
4536 BOOST_LEAF_ASSERT(!x.ctx_ || x.ctx_->captured_id_);
4537 (void) new(&ctx_) context_ptr(std::move(x.ctx_));
4538 default:
4539 break;
4540 }
4541 return x_what;
4542 }
4543
4544 result( result_discriminant && what ) noexcept:
4545 what_(std::move(what))
4546 {
4547 BOOST_LEAF_ASSERT(what_.kind()==result_discriminant::err_id || what_.kind()==result_discriminant::no_error);
4548 }
4549
4550 error_id get_error_id() const noexcept
4551 {
4552 BOOST_LEAF_ASSERT(what_.kind()!=result_discriminant::val);
4553 return what_.kind()==result_discriminant::ctx_ptr ? ctx_->captured_id_ : what_.get_error_id();
4554 }
4555
4556 static int init_T_with_U( T && );
4557
4558 protected:
4559
4560 void enforce_value_state() const
4561 {
4562 if( what_.kind() != result_discriminant::val )
4563 ::boost::leaf::throw_exception(bad_result(get_error_id()));
4564 }
4565
4566 public:
4567
4568 result( result && x ) noexcept:
4569 what_(move_from(std::move(x)))
4570 {
4571 }
4572
4573 template <class U>
4574 result( result<U> && x ) noexcept:
4575 what_(move_from(std::move(x)))
4576
4577 {
4578 }
4579
4580 result():
4581 stored_(stored_type()),
4582 what_(result_discriminant::kind_val{})
4583 {
4584 }
4585
4586 result( value_type && v ) noexcept:
4587 stored_(std::forward<value_type>(v)),
4588 what_(result_discriminant::kind_val{})
4589 {
4590 }
4591
4592 result( value_type const & v ):
4593 stored_(v),
4594 what_(result_discriminant::kind_val{})
4595 {
4596 }
4597
4598 result( error_id err ) noexcept:
4599 what_(err)
4600 {
4601 }
4602
4603 // SFINAE: T can be initialized with a U, e.g. result<std::string>("literal").
4604 // Not using is_constructible on purpose, bug with COMPILER=/usr/bin/clang++ CXXSTD=11 clang 3.3.
4605 template <class U>
4606 result( U && u, decltype(init_T_with_U(std::forward<U>(u))) * = 0 ):
4607 stored_(std::forward<U>(u)),
4608 what_(result_discriminant::kind_val{})
4609 {
4610 }
4611
4612 result( std::error_code const & ec ) noexcept:
4613 what_(error_id(ec))
4614 {
4615 }
4616
4617 template <class Enum>
4618 result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, int>::type * = 0 ) noexcept:
4619 what_(error_id(e))
4620 {
4621 }
4622
4623 result( context_ptr && ctx ) noexcept:
4624 ctx_(std::move(ctx)),
4625 what_(result_discriminant::kind_ctx_ptr{})
4626 {
4627 }
4628
4629 ~result() noexcept
4630 {
4631 destroy();
4632 }
4633
4634 result & operator=( result && x ) noexcept
4635 {
4636 destroy();
4637 what_ = move_from(std::move(x));
4638 return *this;
4639 }
4640
4641 template <class U>
4642 result & operator=( result<U> && x ) noexcept
4643 {
4644 destroy();
4645 what_ = move_from(std::move(x));
4646 return *this;
4647 }
4648
4649 explicit operator bool() const noexcept
4650 {
4651 return what_.kind() == result_discriminant::val;
4652 }
4653
4654 value_cref value() const &
4655 {
4656 enforce_value_state();
4657 return stored_;
4658 }
4659
4660 value_ref value() &
4661 {
4662 enforce_value_state();
4663 return stored_;
4664 }
4665
4666 value_rv_cref value() const &&
4667 {
4668 enforce_value_state();
4669 return std::move(stored_);
4670 }
4671
4672 value_rv_ref value() &&
4673 {
4674 enforce_value_state();
4675 return std::move(stored_);
4676 }
4677
4678 value_cref operator*() const &
4679 {
4680 return value();
4681 }
4682
4683 value_ref operator*() &
4684 {
4685 return value();
4686 }
4687
4688 value_rv_cref operator*() const &&
4689 {
4690 return value();
4691 }
4692
4693 value_rv_ref operator*() &&
4694 {
4695 return value();
4696 }
4697
4698 value_type_const * operator->() const
4699 {
4700 return &value();
4701 }
4702
4703 value_type * operator->()
4704 {
4705 return &value();
4706 }
4707
4708 error_result error() noexcept
4709 {
4710 return error_result{*this};
4711 }
4712
4713 template <class... Item>
4714 error_id load( Item && ... item ) noexcept
4715 {
4716 return error_id(error()).load(std::forward<Item>(item)...);
4717 }
4718 };
4719
4720 ////////////////////////////////////////
4721
4722 namespace leaf_detail
4723 {
4724 struct void_ { };
4725 }
4726
4727 template <>
4728 class result<void>:
4729 result<leaf_detail::void_>
4730 {
4731 using result_discriminant = leaf_detail::result_discriminant;
4732 using void_ = leaf_detail::void_;
4733 using base = result<void_>;
4734
4735 template <class U>
4736 friend class result;
4737
4738 result( result_discriminant && what ) noexcept:
4739 base(std::move(what))
4740 {
4741 }
4742
4743 public:
4744
4745 using value_type = void;
4746
4747 result( result && x ) noexcept:
4748 base(std::move(x))
4749 {
4750 }
4751
4752 result() noexcept
4753 {
4754 }
4755
4756 result( error_id err ) noexcept:
4757 base(err)
4758 {
4759 }
4760
4761 result( std::error_code const & ec ) noexcept:
4762 base(ec)
4763 {
4764 }
4765
4766 template <class Enum>
4767 result( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
4768 base(e)
4769 {
4770 }
4771
4772 result( context_ptr && ctx ) noexcept:
4773 base(std::move(ctx))
4774 {
4775 }
4776
4777 ~result() noexcept
4778 {
4779 }
4780
4781 void value() const
4782 {
4783 base::enforce_value_state();
4784 }
4785
4786 using base::operator=;
4787 using base::operator bool;
4788 using base::get_error_id;
4789 using base::error;
4790 using base::load;
4791 };
4792
4793 ////////////////////////////////////////
4794
4795 template <class R>
4796 struct is_result_type;
4797
4798 template <class T>
4799 struct is_result_type<result<T>>: std::true_type
4800 {
4801 };
4802
4803 } }
4804
4805 #endif
4806 // <<< #include <boost/leaf/result.hpp>
4807 #line 18 "../../include/boost/leaf/detail/all.hpp"
4808
4809 #endif