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 optional()727 BOOST_LEAF_CONSTEXPR optional() noexcept: 728 key_(0) 729 { 730 } 731 optional(optional const & x)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 optional(optional && x)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 optional(int key,T const & v)749 BOOST_LEAF_CONSTEXPR optional( int key, T const & v ): 750 key_(key), 751 value_(v) 752 { 753 BOOST_LEAF_ASSERT(!empty()); 754 } 755 optional(int key,T && v)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 operator =(optional const & x)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 operator =(optional && x)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 ~optional()785 ~optional() noexcept 786 { 787 reset(); 788 } 789 empty() const790 BOOST_LEAF_CONSTEXPR bool empty() const noexcept 791 { 792 return key_==0; 793 } 794 key() const795 BOOST_LEAF_CONSTEXPR int key() const noexcept 796 { 797 return key_; 798 } 799 reset()800 BOOST_LEAF_CONSTEXPR void reset() noexcept 801 { 802 if( key_ ) 803 { 804 value_.~T(); 805 key_=0; 806 } 807 } 808 put(int key,T const & v)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 put(int key,T && v)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 has_value(int key) const827 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 has_value(int key)833 BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept 834 { 835 BOOST_LEAF_ASSERT(key); 836 return key_==key ? &value_ : 0; 837 } 838 value(int key) const839 BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept 840 { 841 BOOST_LEAF_ASSERT(has_value(key) != 0); 842 return value_; 843 } 844 value(int key)845 BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept 846 { 847 BOOST_LEAF_ASSERT(has_value(key) != 0); 848 return value_; 849 } 850 value(int key) const851 BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept 852 { 853 BOOST_LEAF_ASSERT(has_value(key) != 0); 854 return value_; 855 } 856 value(int key)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> check_prefix(char const * t,char const (& prefix)[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> type()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; printboost::leaf::leaf_detail::diagnostic947 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; printboost::leaf::leaf_detail::diagnostic957 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; printboost::leaf::leaf_detail::diagnostic967 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; printboost::leaf::leaf_detail::diagnostic978 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> operator +(inject_loc loc,T && x)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> throw_exception(T const & e)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> throw_exception(T const & e)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 e_unexpected_count(char const * (* first_type)())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> print(std::basic_ostream<CharT,Traits> & os) const1126 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; printboost::leaf::leaf_detail::diagnostic1143 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 e_unexpected_info()1153 e_unexpected_info() noexcept 1154 { 1155 } 1156 1157 template <class E> add(E && 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> print(std::basic_ostream<CharT,Traits> & os) const1170 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; printboost::leaf::leaf_detail::diagnostic1180 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> operator <<(std::basic_ostream<CharT,Traits> & os,e_source_location const & x)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 slot()1243 BOOST_LEAF_CONSTEXPR slot() noexcept: 1244 top_(0) 1245 { 1246 } 1247 slot(slot && x)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 activate()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 deactivate()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> print(std::basic_ostream<CharT,Traits> & os,int key_to_print) const1272 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> load_unexpected_count(int err_id)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> load_unexpected_info(int err_id,E && 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> load_unexpected(int err_id,E && 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> propagate()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> load_slot(int err_id,E && 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> accumulate_slot(int err_id,F && 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 generate_next_idboost::leaf::leaf_detail::id_factory1396 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 current_id()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 new_id()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 { loadboost::leaf::leaf_detail::load_item1437 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 { loadboost::leaf::leaf_detail::load_item1446 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 { loadboost::leaf::leaf_detail::load_item1455 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 { equivalent(int,std::error_condition const &) const1468 bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } equivalent(std::error_code const &,int) const1469 bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } name() const1470 char const * name() const noexcept final override { return "LEAF error"; } message(int condition) const1471 std::string message( int condition ) const final override { return name(); } 1472 public: ~leaf_category()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 import_error_code(std::error_code const & ec)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 is_error_id(std::error_code const & ec)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 error_id(int value)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 error_id()1537 BOOST_LEAF_CONSTEXPR error_id() noexcept: 1538 value_(0) 1539 { 1540 } 1541 error_id(std::error_code const & ec)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> error_id(Enum e,typename std::enable_if<std::is_error_code_enum<Enum>::value,Enum>::type * =0)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 load() const1554 BOOST_LEAF_CONSTEXPR error_id load() const noexcept 1555 { 1556 return *this; 1557 } 1558 1559 template <class... Item> load(Item &&...item) const1560 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 to_error_code() const1570 std::error_code to_error_code() const noexcept 1571 { 1572 return std::error_code(value_, leaf_detail::get_error_category<>::cat); 1573 } 1574 value() const1575 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 operator bool() const1586 BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept 1587 { 1588 return value_ != 0; 1589 } 1590 operator ==(error_id a,error_id b)1591 BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept 1592 { 1593 return a.value_ == b.value_; 1594 } 1595 operator !=(error_id a,error_id b)1596 BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept 1597 { 1598 return !(a == b); 1599 } 1600 operator <(error_id a,error_id b)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> operator <<(std::basic_ostream<CharT,Traits> & os,error_id x)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 load_source_location_(char const * file,int line,char const * function) const1612 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 { make_error_id(int err_id)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 new_error()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> new_error(Item &&...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 current_error()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 context_activator(Ctx & ctx)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 context_activator(context_activator && x)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 ~context_activator()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> activate_context(Ctx & 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> operator +(throw_with_loc loc,Ex const & 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 { enforce_std_exception(std::exception const &)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 exception_base()1790 exception_base(): 1791 auto_id_bump_(0, [](void const *) { (void) new_id(); }) 1792 { 1793 } 1794 ~exception_base()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 { get_error_id() const1804 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 exception(error_id id,Ex && ex)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 exception(error_id id)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 exception(Ex && ex,E &&...e)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 exception(E1 && car,E &&...cdr)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 exception()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 error_monitor()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 check_id() const1911 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 get_id() const1930 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 check() const1939 error_id check() const noexcept 1940 { 1941 return leaf_detail::make_error_id(check_id()); 1942 } 1943 assigned_error_id() const1944 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 { triggerboost::leaf::leaf_detail::tuple_for_each_preload1957 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 { triggerboost::leaf::leaf_detail::tuple_for_each_preload1968 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 preloaded_item(E && e)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 trigger(int err_id)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 deferred_item(F && f)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 trigger(int err_id)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 accumulating_item(F && f)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 trigger(int err_id)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 preloaded(Item &&...i)2081 BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): 2082 p_(std::forward<Item>(i)...), 2083 moved_(false) 2084 { 2085 } 2086 preloaded(preloaded && x)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 ~preloaded()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...> on_error(Item &&...i)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>())...)) capture_impl(is_result_tag<R,false>,context_ptr && ctx,F && f,A...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>())...)) capture_impl(is_result_tag<R,true>,context_ptr && ctx,F && f,A...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()) future_get_impl(is_result_tag<R,false>,Future & fut)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()) future_get_impl(is_result_tag<R,true>,Future & fut)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 capturing_exception(std::exception_ptr && ex,context_ptr && ctx)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 unload_and_rethrow_original_exception() const2227 [[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> print(std::basic_ostream<CharT,Traits> & os) const2236 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>())...)) capture_impl(is_result_tag<R,false>,context_ptr && ctx,F && f,A...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>())...)) capture_impl(is_result_tag<R,true>,context_ptr && ctx,F && f,A...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()) future_get_impl(is_result_tag<R,false>,Future & fut)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()) future_get_impl(is_result_tag<R,true>,Future & fut)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>())...)) capture(context_ptr && ctx,F && f,A...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()) future_get(Future & fut)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 { catch_exceptions_helper(std::exception const & ex,leaf_detail_mp11::mp_list<>)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> catch_exceptions_helper(std::exception const & ex,leaf_detail_mp11::mp_list<Ex1,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>> exception_to_result(F && 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> operator <<(std::basic_ostream<CharT,Traits> & os,e_errno const & err)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> operator <<(std::basic_ostream<CharT,Traits> os,e_LastError const & err)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> getboost::leaf::leaf_detail::handler_argument_traits_defaults2580 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> checkboost::leaf::leaf_detail::handler_argument_traits_defaults2598 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> getboost::leaf::leaf_detail::handler_argument_traits_defaults2605 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> checkboost::leaf::leaf_detail::handler_argument_always_available2618 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> getboost::leaf::leaf_detail::handler_argument_traits2649 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> getboost::leaf::leaf_detail::handler_argument_traits2659 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 { activateboost::leaf::leaf_detail::tuple_for_each2679 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 deactivateboost::leaf::leaf_detail::tuple_for_each2686 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 propagateboost::leaf::leaf_detail::tuple_for_each2693 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 propagate_capturedboost::leaf::leaf_detail::tuple_for_each2701 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 printboost::leaf::leaf_detail::tuple_for_each2710 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 { activateboost::leaf::leaf_detail::tuple_for_each2721 BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { } deactivateboost::leaf::leaf_detail::tuple_for_each2722 BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { } propagateboost::leaf::leaf_detail::tuple_for_each2723 BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { } propagate_capturedboost::leaf::leaf_detail::tuple_for_each2724 BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { } printboost::leaf::leaf_detail::tuple_for_each2725 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 propagate_captured_errors(error_id err_id)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 context(context && x)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 context()2828 BOOST_LEAF_CONSTEXPR context() noexcept: 2829 is_active_(false) 2830 { 2831 } 2832 ~context()2833 ~context() noexcept 2834 { 2835 BOOST_LEAF_ASSERT(!is_active()); 2836 } 2837 tup() const2838 BOOST_LEAF_CONSTEXPR Tup const & tup() const noexcept 2839 { 2840 return tup_; 2841 } 2842 tup()2843 BOOST_LEAF_CONSTEXPR Tup & tup() noexcept 2844 { 2845 return tup_; 2846 } 2847 activate()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 deactivate()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 propagate()2879 BOOST_LEAF_CONSTEXPR void propagate() noexcept 2880 { 2881 leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_); 2882 } 2883 is_active() const2884 BOOST_LEAF_CONSTEXPR bool is_active() const noexcept 2885 { 2886 return is_active_; 2887 } 2888 print(std::ostream & os) const2889 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 { propagate_captured_errorsboost::leaf::leaf_detail::polymorphic_context_impl2941 error_id propagate_captured_errors() noexcept final override { return Ctx::propagate_captured_errors(captured_id_); } activateboost::leaf::leaf_detail::polymorphic_context_impl2942 void activate() noexcept final override { Ctx::activate(); } deactivateboost::leaf::leaf_detail::polymorphic_context_impl2943 void deactivate() noexcept final override { Ctx::deactivate(); } propagateboost::leaf::leaf_detail::polymorphic_context_impl2944 void propagate() noexcept final override { Ctx::propagate(); } is_activeboost::leaf::leaf_detail::polymorphic_context_impl2945 bool is_active() const noexcept final override { return Ctx::is_active(); } printboost::leaf::leaf_detail::polymorphic_context_impl2946 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> make_context()2956 BOOST_LEAF_CONSTEXPR inline context_type_from_handlers<H...> make_context() noexcept 2957 { 2958 return { }; 2959 } 2960 2961 template <class... H> make_context(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> make_shared_context()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> make_shared_context(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 scoped_demangled_name(char const * name)3068 explicit scoped_demangled_name( char const * name ) noexcept : 3069 m_p( demangle_alloc( name ) ) 3070 { 3071 } 3072 ~scoped_demangled_name()3073 ~scoped_demangled_name() noexcept 3074 { 3075 demangle_free( m_p ); 3076 } 3077 get() const3078 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 demangle_alloc(char const * name)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 demangle_free(char const * name)3096 inline void demangle_free( char const * name ) noexcept 3097 { 3098 std::free( const_cast< char* >( name ) ); 3099 } 3100 demangle(char const * name)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 demangle_alloc(char const * name)3112 inline char const * demangle_alloc( char const * name ) noexcept 3113 { 3114 return name; 3115 } 3116 demangle_free(char const *)3117 inline void demangle_free( char const * ) noexcept 3118 { 3119 } 3120 demangle(char const * name)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 unpack_error_id(std::exception const * ex)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> print(std::basic_ostream<CharT,Traits> & os) const3172 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 error_info(error_id id)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 error_info(std::exception * ex)3196 explicit error_info( std::exception * ex ) noexcept: 3197 ex_(ex), 3198 err_id_(unpack_error_id(ex_)) 3199 { 3200 } 3201 #endif 3202 error() const3203 BOOST_LEAF_CONSTEXPR error_id error() const noexcept 3204 { 3205 return err_id_; 3206 } 3207 exception() const3208 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> operator <<(std::basic_ostream<CharT,Traits> & os,error_info const & x)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> diagnostic_info(error_info const & ei,leaf_detail::e_unexpected_count const * e_uc,Tup const & 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> operator <<(std::basic_ostream<CharT,Traits> & os,diagnostic_info const & x)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> diagnostic_info_boost::leaf::leaf_detail::diagnostic_info_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> getboost::leaf::leaf_detail::handler_argument_traits3279 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 diagnostic_info(error_info const & ei)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> operator <<(std::basic_ostream<CharT,Traits> & os,diagnostic_info const & x)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 { diagnostic_info_boost::leaf::leaf_detail::diagnostic_info_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> getboost::leaf::leaf_detail::handler_argument_traits3326 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> verbose_diagnostic_info(error_info const & ei,leaf_detail::e_unexpected_info const * e_ui,Tup const & 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> operator <<(std::basic_ostream<CharT,Traits> & os,verbose_diagnostic_info const & x)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> verbose_diagnostic_info_boost::leaf::leaf_detail::verbose_diagnostic_info_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> getboost::leaf::leaf_detail::handler_argument_traits3388 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 verbose_diagnostic_info(error_info const & ei)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> operator <<(std::basic_ostream<CharT,Traits> & os,verbose_diagnostic_info const & x)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 { verbose_diagnostic_info_boost::leaf::leaf_detail::verbose_diagnostic_info_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> getboost::leaf::leaf_detail::handler_argument_traits3436 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 { peekboost::leaf::leaf_detail::peek_exception3481 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 { peekboost::leaf::leaf_detail::peek_exception3490 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 { peekboost::leaf::leaf_detail::peek_exception3499 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 { peekboost::leaf::leaf_detail::peek_exception3514 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 { peekboost::leaf::leaf_detail::peek_exception3529 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 { peekboost::leaf::leaf_detail::peek_exception3538 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 * peek(SlotsTuple const & tup,error_info const & ei)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 * peek(SlotsTuple & tup,error_info const & ei)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>:: check(Tup const & tup,error_info const & ei)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>:: check(Tup & tup,error_info const & ei)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>:: check(Tup const &,error_info const & ei)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 { checkboost::leaf::leaf_detail::check_arguments3616 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 { checkboost::leaf::leaf_detail::check_arguments3625 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> check_handler_(Tup & tup,error_info const & ei,leaf_detail_mp11::mp_list<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> callboost::leaf::leaf_detail::handler_caller3667 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> callboost::leaf::leaf_detail::handler_caller3679 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 handle_error_(Tup & tup,error_info const & ei,H && h)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 handle_error_(Tup & tup,error_info const & ei,Car && car,Cdr &&...cdr)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 handle_error_tuple_(Tup & tup,error_info const & ei,leaf_detail_mp11::index_sequence<I...>,HTup && htup)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 handle_error_tuple_(Tup & tup,error_info const & ei,leaf_detail_mp11::index_sequence<I...>,HTup && htup,Cdr &&...cdr)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 handle_error_(Tup & tup,error_info const & ei,H && h)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 handle_error_(Tup & tup,error_info const & ei,Car && car,Cdr &&...cdr)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...>:: handle_error(error_id id,H &&...h) const3765 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...>:: handle_error(error_id id,H &&...h)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 try_handle_all(TryBlock && try_block,H &&...h)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 try_handle_some(TryBlock && try_block,H &&...h)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>()()) try_catch(TryBlock && try_block,H &&...)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>()()) try_catch_(Ctx & ctx,TryBlock && try_block,H &&...h)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 try_handle_all(TryBlock && try_block,H &&...h)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 try_handle_some(TryBlock && try_block,H &&...h)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>()()) try_catch(TryBlock && try_block,H &&...h)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> get_exception(error_info const & ei)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> checkboost::leaf::leaf_detail::handler_argument_traits3999 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> getboost::leaf::leaf_detail::handler_argument_traits4009 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> cmp_value_pack(MatchType const & e,bool (* P)(T)noexcept)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> cmp_value_pack(MatchType const & e,bool (* P)(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> cmp_value_pack(MatchType const & e,V 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> cmp_value_pack(MatchType const & e,VCar car,VCdr...cdr)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> category(std::error_code const & ec)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> evaluateboost::leaf::match4140 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 evaluateboost::leaf::match4152 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 evaluateboost::leaf::match_value4192 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 evaluateboost::leaf::match_value4204 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 evaluateboost::leaf::match_member4227 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> evaluateboost::leaf::if_not4248 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> check_exception_pack(std::exception const & ex,Ex const *)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> check_exception_pack(std::exception const & ex,Ex const *,ExRest const * ...ex_rest)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 check_exception_pack(std::exception const &)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 evaluateboost::leaf::catch_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 evaluateboost::leaf::catch_4302 BOOST_LEAF_CONSTEXPR static Ex const * evaluate(std::exception const & ex) noexcept 4303 { 4304 return dynamic_cast<Ex const *>(&ex); 4305 } 4306 catch_boost::leaf::catch_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 { what() const4353 char const * what() const noexcept final override 4354 { 4355 return "boost::leaf::bad_result"; 4356 } 4357 4358 public: 4359 bad_result(error_id id)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 result_discriminant(error_id id)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 { }; result_discriminant(kind_val)4416 explicit result_discriminant( kind_val ) noexcept: 4417 state_(val) 4418 { 4419 } 4420 4421 struct kind_ctx_ptr { }; result_discriminant(kind_ctx_ptr)4422 explicit result_discriminant( kind_ctx_ptr ) noexcept: 4423 state_(ctx_ptr) 4424 { 4425 } 4426 kind() const4427 kind_t kind() const noexcept 4428 { 4429 return kind_t(state_&3); 4430 } 4431 get_error_id() const4432 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 error_resultboost::leaf::result::error_result4458 error_result( result & r ) noexcept: 4459 r_(r) 4460 { 4461 } 4462 4463 template <class U> operator result<U>boost::leaf::result::error_result4464 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 operator error_idboost::leaf::result::error_result4477 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 destroy() const4511 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> move_from(result<U> && x)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 result(result_discriminant && what)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 get_error_id() const4550 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 enforce_value_state() const4560 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 result(result && x)4568 result( result && x ) noexcept: 4569 what_(move_from(std::move(x))) 4570 { 4571 } 4572 4573 template <class U> result(result<U> && x)4574 result( result<U> && x ) noexcept: 4575 what_(move_from(std::move(x))) 4576 4577 { 4578 } 4579 result()4580 result(): 4581 stored_(stored_type()), 4582 what_(result_discriminant::kind_val{}) 4583 { 4584 } 4585 result(value_type && v)4586 result( value_type && v ) noexcept: 4587 stored_(std::forward<value_type>(v)), 4588 what_(result_discriminant::kind_val{}) 4589 { 4590 } 4591 result(value_type const & v)4592 result( value_type const & v ): 4593 stored_(v), 4594 what_(result_discriminant::kind_val{}) 4595 { 4596 } 4597 result(error_id err)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> result(U && u,decltype(init_T_with_U (std::forward<U> (u)))* =0)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 result(std::error_code const & ec)4612 result( std::error_code const & ec ) noexcept: 4613 what_(error_id(ec)) 4614 { 4615 } 4616 4617 template <class Enum> result(Enum e,typename std::enable_if<std::is_error_code_enum<Enum>::value,int>::type * =0)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 result(context_ptr && ctx)4623 result( context_ptr && ctx ) noexcept: 4624 ctx_(std::move(ctx)), 4625 what_(result_discriminant::kind_ctx_ptr{}) 4626 { 4627 } 4628 ~result()4629 ~result() noexcept 4630 { 4631 destroy(); 4632 } 4633 operator =(result && x)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> operator =(result<U> && x)4642 result & operator=( result<U> && x ) noexcept 4643 { 4644 destroy(); 4645 what_ = move_from(std::move(x)); 4646 return *this; 4647 } 4648 operator bool() const4649 explicit operator bool() const noexcept 4650 { 4651 return what_.kind() == result_discriminant::val; 4652 } 4653 value() const4654 value_cref value() const & 4655 { 4656 enforce_value_state(); 4657 return stored_; 4658 } 4659 value()4660 value_ref value() & 4661 { 4662 enforce_value_state(); 4663 return stored_; 4664 } 4665 value() const4666 value_rv_cref value() const && 4667 { 4668 enforce_value_state(); 4669 return std::move(stored_); 4670 } 4671 value()4672 value_rv_ref value() && 4673 { 4674 enforce_value_state(); 4675 return std::move(stored_); 4676 } 4677 operator *() const4678 value_cref operator*() const & 4679 { 4680 return value(); 4681 } 4682 operator *()4683 value_ref operator*() & 4684 { 4685 return value(); 4686 } 4687 operator *() const4688 value_rv_cref operator*() const && 4689 { 4690 return value(); 4691 } 4692 operator *()4693 value_rv_ref operator*() && 4694 { 4695 return value(); 4696 } 4697 operator ->() const4698 value_type_const * operator->() const 4699 { 4700 return &value(); 4701 } 4702 operator ->()4703 value_type * operator->() 4704 { 4705 return &value(); 4706 } 4707 error()4708 error_result error() noexcept 4709 { 4710 return error_result{*this}; 4711 } 4712 4713 template <class... Item> load(Item &&...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 result(result_discriminant && what)4738 result( result_discriminant && what ) noexcept: 4739 base(std::move(what)) 4740 { 4741 } 4742 4743 public: 4744 4745 using value_type = void; 4746 result(result && x)4747 result( result && x ) noexcept: 4748 base(std::move(x)) 4749 { 4750 } 4751 result()4752 result() noexcept 4753 { 4754 } 4755 result(error_id err)4756 result( error_id err ) noexcept: 4757 base(err) 4758 { 4759 } 4760 result(std::error_code const & ec)4761 result( std::error_code const & ec ) noexcept: 4762 base(ec) 4763 { 4764 } 4765 4766 template <class Enum> result(Enum e,typename std::enable_if<std::is_error_code_enum<Enum>::value,Enum>::type * =0)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 result(context_ptr && ctx)4772 result( context_ptr && ctx ) noexcept: 4773 base(std::move(ctx)) 4774 { 4775 } 4776 ~result()4777 ~result() noexcept 4778 { 4779 } 4780 value() const4781 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 4810