#ifndef BOOST_LEAF_HPP_INCLUDED #define BOOST_LEAF_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // >>> #include #line 1 "boost/leaf/capture.hpp" #ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED #define BOOST_LEAF_CAPTURE_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/exception.hpp" #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/error.hpp" #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED #define BOOST_LEAF_ERROR_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/detail/function_traits.hpp" #ifndef BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED #define BOOST_LEAF_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/detail/mp11.hpp" #ifndef BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED #define BOOST_LEAF_DETAIL_MP11_HPP_INCLUDED // Copyright 2015-2017 Peter Dimov. // Copyright 2019 Emil Dotchevski. // // Distributed under the Boost Software License, Version 1.0. // // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt #include #include namespace boost { namespace leaf { namespace leaf_detail_mp11 { // mp_list template struct mp_list { }; // mp_identity template struct mp_identity { using type = T; }; // mp_inherit template struct mp_inherit: T... {}; // mp_if, mp_if_c namespace detail { template struct mp_if_c_impl { }; template struct mp_if_c_impl { using type = T; }; template struct mp_if_c_impl { using type = E; }; } // namespace detail template using mp_if_c = typename detail::mp_if_c_impl::type; template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; // mp_bool template using mp_bool = std::integral_constant; using mp_true = mp_bool; using mp_false = mp_bool; // mp_to_bool template using mp_to_bool = mp_bool( T::value )>; // mp_not template using mp_not = mp_bool< !T::value >; // mp_int template using mp_int = std::integral_constant; // mp_size_t template using mp_size_t = std::integral_constant; // mp_set_contains namespace detail { template struct mp_set_contains_impl; template class L, class... T, class V> struct mp_set_contains_impl, V> { using type = mp_to_bool, mp_inherit...> > >; }; } // namespace detail template using mp_set_contains = typename detail::mp_set_contains_impl::type; // mp_set_push_back namespace detail { template struct mp_set_push_back_impl; template class L, class... U> struct mp_set_push_back_impl> { using type = L; }; template class L, class... U, class T1, class... T> struct mp_set_push_back_impl, T1, T...> { using S = mp_if, T1>, L, L>; using type = typename mp_set_push_back_impl::type; }; } // namespace detail template using mp_set_push_back = typename detail::mp_set_push_back_impl::type; // mp_unique namespace detail { template struct mp_unique_impl; template class L, class... T> struct mp_unique_impl> { using type = mp_set_push_back, T...>; }; } // namespace detail template using mp_unique = typename detail::mp_unique_impl::type; // mp_append namespace detail { template struct mp_append_impl; template<> struct mp_append_impl<> { using type = mp_list<>; }; template class L, class... T> struct mp_append_impl> { using type = L; }; template class L1, class... T1, template class L2, class... T2, class... Lr> struct mp_append_impl, L2, Lr...> { using type = typename mp_append_impl, Lr...>::type; }; } template using mp_append = typename detail::mp_append_impl::type; // mp_front namespace detail { template struct mp_front_impl { // An error "no type named 'type'" here means that the argument to mp_front // is either not a list, or is an empty list }; template class L, class T1, class... T> struct mp_front_impl> { using type = T1; }; } // namespace detail template using mp_front = typename detail::mp_front_impl::type; // mp_pop_front namespace detail { template struct mp_pop_front_impl { // An error "no type named 'type'" here means that the argument to mp_pop_front // is either not a list, or is an empty list }; template class L, class T1, class... T> struct mp_pop_front_impl> { using type = L; }; } // namespace detail template using mp_pop_front = typename detail::mp_pop_front_impl::type; // mp_first template using mp_first = mp_front; // mp_rest template using mp_rest = mp_pop_front; // mp_remove_if namespace detail { template class P> struct mp_remove_if_impl; template class L, class... T, template class P> struct mp_remove_if_impl, P> { template using _f = mp_if, mp_list<>, mp_list>; using type = mp_append, _f...>; }; } // namespace detail template class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; // integer_sequence template struct integer_sequence { }; // detail::make_integer_sequence_impl namespace detail { // iseq_if_c template struct iseq_if_c_impl; template struct iseq_if_c_impl { using type = T; }; template struct iseq_if_c_impl { using type = E; }; template using iseq_if_c = typename iseq_if_c_impl::type; // iseq_identity template struct iseq_identity { using type = T; }; template struct append_integer_sequence; template struct append_integer_sequence, integer_sequence> { using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >; }; template struct make_integer_sequence_impl; template struct make_integer_sequence_impl_ { private: static_assert( N >= 0, "make_integer_sequence: N must not be negative" ); static T const M = N / 2; static T const R = N % 2; using S1 = typename make_integer_sequence_impl::type; using S2 = typename append_integer_sequence::type; using S3 = typename make_integer_sequence_impl::type; using S4 = typename append_integer_sequence::type; public: using type = S4; }; template struct make_integer_sequence_impl: iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_ > > { }; } // namespace detail // make_integer_sequence template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; // index_sequence template using index_sequence = integer_sequence; // make_index_sequence template using make_index_sequence = make_integer_sequence; // index_sequence_for template using index_sequence_for = make_integer_sequence; // implementation by Bruno Dutra (by the name is_evaluable) namespace detail { template class F, class... T> struct mp_valid_impl { template class G, class = G> static mp_true check(int); template class> static mp_false check(...); using type = decltype(check(0)); }; } // namespace detail template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; } } } #endif // <<< #include #line 20 "boost/leaf/detail/function_traits.hpp" #include namespace boost { namespace leaf { namespace leaf_detail { template struct gcc49_workaround //Thanks Glen Fernandes { using type = void; }; template using void_t = typename gcc49_workaround::type; template struct function_traits { constexpr static int arity = -1; }; template struct function_traits> { private: using tr = function_traits; public: using return_type = typename tr::return_type; static constexpr int arity = tr::arity - 1; using mp_args = typename leaf_detail_mp11::mp_rest; template struct arg: tr::template arg { }; }; template struct function_traits { using return_type = R; static constexpr int arity = sizeof...(A); using mp_args = leaf_detail_mp11::mp_list; template struct arg { static_assert(I < arity, "I out of range"); using type = typename std::tuple_element>::type; }; }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template struct function_traits : function_traits { }; template using fn_return_type = typename function_traits::return_type; template using fn_arg_type = typename function_traits::template arg::type; template using fn_mp_args = typename function_traits::mp_args; } } } #endif // <<< #include #line 20 "boost/leaf/error.hpp" // >>> #include #line 1 "boost/leaf/detail/print.hpp" #ifndef BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED #define BOOST_LEAF_DETAIL_PRINT_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/detail/optional.hpp" #ifndef BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED #define BOOST_LEAF_DETAIL_OPTIONAL_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif // >>> #include #line 1 "boost/leaf/detail/config.hpp" #ifndef BOOST_LEAF_CONFIG_HPP_INCLUDED #define BOOST_LEAF_CONFIG_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // The following is based on Boost Config. // (C) Copyright John Maddock 2001 - 2003. // (C) Copyright Martin Wille 2003. // (C) Copyright Guillaume Melquiond 2003. #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif //////////////////////////////////////// // Configure BOOST_LEAF_NO_EXCEPTIONS, unless already #defined #ifndef BOOST_LEAF_NO_EXCEPTIONS # if defined(__clang__) && !defined(__ibmxl__) // Clang C++ emulates GCC, so it has to appear early. # if !__has_feature(cxx_exceptions) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__DMC__) // Digital Mars C++ # if !defined(_CPPUNWIND) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__GNUC__) && !defined(__ibmxl__) // GNU C++: # if !defined(__EXCEPTIONS) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__KCC) // Kai C++ # if !defined(_EXCEPTIONS) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__CODEGEARC__) // CodeGear - must be checked for before Borland # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__BORLANDC__) // Borland # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__MWERKS__) // Metrowerks CodeWarrior # if !__option(exceptions) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__IBMCPP__) && defined(__COMPILER_VER__) && defined(__MVS__) // IBM z/OS XL C/C++ # if !defined(_CPPUNWIND) && !defined(__EXCEPTIONS) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(__ibmxl__) // IBM XL C/C++ for Linux (Little Endian) # if !__has_feature(cxx_exceptions) # define BOOST_LEAF_NO_EXCEPTIONS # endif # elif defined(_MSC_VER) // Microsoft Visual C++ // // Must remain the last #elif since some other vendors (Metrowerks, for // example) also #define _MSC_VER # if !defined(_CPPUNWIND) # define BOOST_LEAF_NO_EXCEPTIONS # endif # endif #endif #ifdef BOOST_NORETURN # define BOOST_LEAF_NORETURN BOOST_NORETURN #else # if defined(_MSC_VER) # define BOOST_LEAF_NORETURN __declspec(noreturn) # elif defined(__GNUC__) # define BOOST_LEAF_NORETURN __attribute__ ((__noreturn__)) # elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130) # if __has_attribute(noreturn) # define BOOST_LEAF_NORETURN [[noreturn]] # endif # elif defined(__has_cpp_attribute) # if __has_cpp_attribute(noreturn) # define BOOST_LEAF_NORETURN [[noreturn]] # endif # endif #endif #if !defined(BOOST_LEAF_NORETURN) # define BOOST_LEAF_NORETURN #endif //////////////////////////////////////// #ifndef BOOST_LEAF_DIAGNOSTICS # define BOOST_LEAF_DIAGNOSTICS 1 #endif #if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1 # error BOOST_LEAF_DIAGNOSTICS must be 0 or 1. #endif //////////////////////////////////////// #ifdef _MSC_VER # define BOOST_LEAF_ALWAYS_INLINE __forceinline #else # define BOOST_LEAF_ALWAYS_INLINE __attribute__((always_inline)) inline #endif //////////////////////////////////////// #ifndef BOOST_LEAF_NODISCARD # if __cplusplus >= 201703L # define BOOST_LEAF_NODISCARD [[nodiscard]] # else # define BOOST_LEAF_NODISCARD # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_CONSTEXPR # if __cplusplus > 201402L # define BOOST_LEAF_CONSTEXPR constexpr # else # define BOOST_LEAF_CONSTEXPR # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_ASSERT # ifdef BOOST_ASSERT # define BOOST_LEAF_ASSERT BOOST_ASSERT # else # include # define BOOST_LEAF_ASSERT assert # endif #endif //////////////////////////////////////// #ifndef BOOST_LEAF_NO_EXCEPTIONS # include # if (defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L) || (defined(_MSC_VER) && _MSC_VER >= 1900) # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 1 # else # define BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 0 # endif #endif #endif // <<< #include #line 20 "boost/leaf/detail/optional.hpp" #include #include namespace boost { namespace leaf { namespace leaf_detail { template class optional { int key_; union { T value_; }; public: typedef T value_type; BOOST_LEAF_CONSTEXPR optional() noexcept: key_(0) { } BOOST_LEAF_CONSTEXPR optional( optional const & x ): key_(x.key_) { if( x.key_ ) (void) new (&value_) T( x.value_ ); } BOOST_LEAF_CONSTEXPR optional( optional && x ) noexcept: key_(x.key_) { if( x.key_ ) { (void) new (&value_) T( std::move(x.value_) ); x.reset(); } } BOOST_LEAF_CONSTEXPR optional( int key, T const & v ): key_(key), value_(v) { BOOST_LEAF_ASSERT(!empty()); } BOOST_LEAF_CONSTEXPR optional( int key, T && v ) noexcept: key_(key), value_(std::move(v)) { BOOST_LEAF_ASSERT(!empty()); } BOOST_LEAF_CONSTEXPR optional & operator=( optional const & x ) { reset(); if( int key = x.key() ) { put(key, x.value_); key_ = key; } return *this; } BOOST_LEAF_CONSTEXPR optional & operator=( optional && x ) noexcept { reset(); if( int key = x.key() ) { put(key, std::move(x.value_)); x.reset(); } return *this; } ~optional() noexcept { reset(); } BOOST_LEAF_CONSTEXPR bool empty() const noexcept { return key_==0; } BOOST_LEAF_CONSTEXPR int key() const noexcept { return key_; } BOOST_LEAF_CONSTEXPR void reset() noexcept { if( key_ ) { value_.~T(); key_=0; } } BOOST_LEAF_CONSTEXPR T & put( int key, T const & v ) { BOOST_LEAF_ASSERT(key); reset(); (void) new(&value_) T(v); key_=key; return value_; } BOOST_LEAF_CONSTEXPR T & put( int key, T && v ) noexcept { BOOST_LEAF_ASSERT(key); reset(); (void) new(&value_) T(std::move(v)); key_=key; return value_; } BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept { BOOST_LEAF_ASSERT(key); return key_==key ? &value_ : 0; } BOOST_LEAF_CONSTEXPR T * has_value(int key) noexcept { BOOST_LEAF_ASSERT(key); return key_==key ? &value_ : 0; } BOOST_LEAF_CONSTEXPR T const & value(int key) const & noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); return value_; } BOOST_LEAF_CONSTEXPR T & value(int key) & noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); return value_; } BOOST_LEAF_CONSTEXPR T const && value(int key) const && noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); return value_; } BOOST_LEAF_CONSTEXPR T value(int key) && noexcept { BOOST_LEAF_ASSERT(has_value(key) != 0); T tmp(std::move(value_)); reset(); return tmp; } }; } } } #endif // <<< #include #line 20 "boost/leaf/detail/print.hpp" #include #include namespace boost { namespace leaf { namespace leaf_detail { template BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] ) { return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t; } } template inline char const * type() { using leaf_detail::check_prefix; char const * t = #ifdef __FUNCSIG__ __FUNCSIG__; #else __PRETTY_FUNCTION__; #endif #if defined(__clang__) BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32); return t+32; #elif defined(__GNUC__) BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32); return t+32; #else char const * clang_style = check_prefix(t,"const char *boost::leaf::type() "); if( clang_style!=t ) return clang_style; char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() "); if( gcc_style!=t ) return gcc_style; #endif return t; } namespace leaf_detail { template struct is_printable: std::false_type { }; template struct is_printable()<(), void())>: std::true_type { }; //////////////////////////////////////// template struct has_printable_member_value: std::false_type { }; template struct has_printable_member_value()<().value, void())>: std::true_type { }; //////////////////////////////////////// template ::value, bool ValuePrintable=has_printable_member_value::value> struct diagnostic; template struct diagnostic { static constexpr bool is_invisible = false; static void print( std::ostream & os, Wrapper const & x ) { os << x; } }; template struct diagnostic { static constexpr bool is_invisible = false; static void print( std::ostream & os, Wrapper const & x ) { os << type() << ": " << x.value; } }; template struct diagnostic { static constexpr bool is_invisible = false; static void print( std::ostream & os, Wrapper const & ) { os << type() << ": {Non-Printable}"; } }; #ifndef BOOST_LEAF_NO_EXCEPTIONS template <> struct diagnostic { static constexpr bool is_invisible = true; BOOST_LEAF_CONSTEXPR static void print( std::ostream &, std::exception_ptr const & ) { } }; #endif } } } #endif // <<< #include #line 21 "boost/leaf/error.hpp" #include #include #include #include #if BOOST_LEAF_DIAGNOSTICS # include # include #endif #define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y) #define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__) #define BOOST_LEAF_ASSIGN(v,r)\ static_assert(::boost::leaf::is_result_type::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\ auto && BOOST_LEAF_TMP = r;\ if( !BOOST_LEAF_TMP )\ return BOOST_LEAF_TMP.error();\ v = std::forward(BOOST_LEAF_TMP).value() #define BOOST_LEAF_AUTO(v, r)\ BOOST_LEAF_ASSIGN(auto v, r) #define BOOST_LEAF_CHECK(r)\ {\ static_assert(::boost::leaf::is_result_type::type>::value, "BOOST_LEAF_CHECK requires a result type");\ auto && BOOST_LEAF_TMP = r;\ if( !BOOST_LEAF_TMP )\ return BOOST_LEAF_TMP.error();\ } #define BOOST_LEAF_NEW_ERROR ::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error namespace boost { namespace leaf { namespace leaf_detail { struct inject_loc { char const * const file; int const line; char const * const fn; template friend T operator+( inject_loc loc, T && x ) noexcept { x.load_source_location_(loc.file, loc.line, loc.fn); return std::move(x); } }; } } } //////////////////////////////////////// #ifdef BOOST_LEAF_NO_EXCEPTIONS namespace boost { BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined } namespace boost { namespace leaf { template BOOST_LEAF_NORETURN void throw_exception( T const & e ) { ::boost::throw_exception(e); } } } #else namespace boost { namespace leaf { template BOOST_LEAF_NORETURN void throw_exception( T const & e ) { throw e; } } } #endif //////////////////////////////////////// #ifdef BOOST_LEAF_NO_THREADS # define BOOST_LEAF_THREAD_LOCAL namespace boost { namespace leaf { namespace leaf_detail { using atomic_unsigned_int = unsigned int; } } } #else # include # include # define BOOST_LEAF_THREAD_LOCAL thread_local namespace boost { namespace leaf { namespace leaf_detail { using atomic_unsigned_int = std::atomic; } } } #endif //////////////////////////////////////// namespace boost { namespace leaf { #if BOOST_LEAF_DIAGNOSTICS namespace leaf_detail { class e_unexpected_count { public: char const * (*first_type)(); int count; BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept: first_type(first_type), count(1) { } template void print( std::basic_ostream & os ) const { BOOST_LEAF_ASSERT(first_type != 0); BOOST_LEAF_ASSERT(count>0); os << "Detected "; if( count==1 ) os << "1 attempt to communicate an unexpected error object"; else os << count << " attempts to communicate unexpected error objects, the first one"; (os << " of type " << first_type() << '\n').flush(); } }; template <> struct diagnostic { static constexpr bool is_invisible = true; BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { } }; class e_unexpected_info { std::string s_; std::set already_; public: e_unexpected_info() noexcept { } template void add(E && e) { if( !diagnostic::is_invisible && already_.insert(&type).second ) { std::stringstream s; diagnostic::print(s,e); (s << '\n').flush(); s_ += s.str(); } } template void print( std::basic_ostream & os ) const { os << "Unhandled error objects:\n" << s_; } }; template <> struct diagnostic { static constexpr bool is_invisible = true; BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { } }; template struct tl_unexpected_enabled { static BOOST_LEAF_THREAD_LOCAL int counter; }; template BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled::counter; } #endif } } //////////////////////////////////////// namespace boost { namespace leaf { struct e_source_location { char const * const file; int const line; char const * const function; template friend std::basic_ostream & operator<<( std::basic_ostream & os, e_source_location const & x ) { return os << leaf::type() << ": " << x.file << '(' << x.line << ") in function " << x.function; } }; //////////////////////////////////////// namespace leaf_detail { template class slot; template struct tl_slot_ptr { static BOOST_LEAF_THREAD_LOCAL slot * p; }; template BOOST_LEAF_THREAD_LOCAL slot * tl_slot_ptr::p; template class slot: optional { slot( slot const & ) = delete; slot & operator=( slot const & ) = delete; using impl = optional; slot * * top_; slot * prev_; public: BOOST_LEAF_CONSTEXPR slot() noexcept: top_(0) { } BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: optional(std::move(x)), top_(0) { BOOST_LEAF_ASSERT(x.top_==0); } BOOST_LEAF_CONSTEXPR void activate() noexcept { BOOST_LEAF_ASSERT(top_==0 || *top_!=this); top_ = &tl_slot_ptr::p; prev_ = *top_; *top_ = this; } BOOST_LEAF_CONSTEXPR void deactivate() noexcept { BOOST_LEAF_ASSERT(top_!=0 && *top_==this); *top_ = prev_; } BOOST_LEAF_CONSTEXPR void propagate() noexcept; template void print( std::basic_ostream & os, int key_to_print ) const { if( !diagnostic::is_invisible ) if( int k = this->key() ) { if( key_to_print ) { if( key_to_print!=k ) return; } else os << '[' << k << ']'; diagnostic::print(os, value(k)); (os << '\n').flush(); } } using impl::put; using impl::has_value; using impl::value; }; #if BOOST_LEAF_DIAGNOSTICS template BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept { if( slot * sl = tl_slot_ptr::p ) if( e_unexpected_count * unx = sl->has_value(err_id) ) ++unx->count; else sl->put(err_id, e_unexpected_count(&type)); } template BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept { if( slot * sl = tl_slot_ptr::p ) if( e_unexpected_info * unx = sl->has_value(err_id) ) unx->add(std::forward(e)); else sl->put(err_id, e_unexpected_info()).add(std::forward(e)); } template BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept { load_unexpected_count(err_id); load_unexpected_info(err_id, std::forward(e)); } #endif template BOOST_LEAF_CONSTEXPR inline void slot::propagate() noexcept { BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this)); if( prev_ ) { impl & that_ = *prev_; if( that_.empty() ) { impl & this_ = *this; that_ = std::move(this_); } } #if BOOST_LEAF_DIAGNOSTICS else { int c = tl_unexpected_enabled<>::counter; BOOST_LEAF_ASSERT(c>=0); if( c ) if( int err_id = impl::key() ) load_unexpected(err_id, std::move(*this).value(err_id)); } #endif } template BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept { static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); using T = typename std::decay::type; BOOST_LEAF_ASSERT((err_id&3)==1); if( slot * p = tl_slot_ptr::p ) (void) p->put(err_id, std::forward(e)); #if BOOST_LEAF_DIAGNOSTICS else { int c = tl_unexpected_enabled<>::counter; BOOST_LEAF_ASSERT(c>=0); if( c ) load_unexpected(err_id, std::forward(e)); } #endif return 0; } template BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept { static_assert(function_traits::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference"); using E = typename std::decay>::type; static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); BOOST_LEAF_ASSERT((err_id&3)==1); if( auto sl = tl_slot_ptr::p ) if( auto v = sl->has_value(err_id) ) (void) std::forward(f)(*v); else (void) std::forward(f)(sl->put(err_id,E())); return 0; } } //////////////////////////////////////// namespace leaf_detail { template struct id_factory { static atomic_unsigned_int counter; static BOOST_LEAF_THREAD_LOCAL unsigned current_id; BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept { auto id = (counter+=4); BOOST_LEAF_ASSERT((id&3)==1); return id; } }; template atomic_unsigned_int id_factory::counter(-3); template BOOST_LEAF_THREAD_LOCAL unsigned id_factory::current_id(0); inline int current_id() noexcept { auto id = id_factory<>::current_id; BOOST_LEAF_ASSERT(id==0 || (id&3)==1); return id; } inline int new_id() noexcept { auto id = id_factory<>::generate_next_id(); return id_factory<>::current_id = id; } } //////////////////////////////////////// namespace leaf_detail { template ::arity> struct load_item { static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument"); }; template struct load_item { BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept { return load_slot(err_id, std::forward(e)); } }; template struct load_item { BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept { return load_slot(err_id, std::forward(f)()); } }; template struct load_item { BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept { return accumulate_slot(err_id, std::forward(f)); } }; } //////////////////////////////////////// namespace leaf_detail { class leaf_category final: public std::error_category { bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } char const * name() const noexcept final override { return "LEAF error"; } std::string message( int condition ) const final override { return name(); } public: ~leaf_category() noexcept final override { } }; template struct get_error_category { static leaf_category cat; }; template leaf_category get_error_category::cat; inline int import_error_code( std::error_code const & ec ) noexcept { if( int err_id = ec.value() ) { std::error_category const & cat = get_error_category<>::cat; if( &ec.category()==&cat ) { BOOST_LEAF_ASSERT((err_id&3)==1); return (err_id&~3)|1; } else { err_id = new_id(); (void) load_slot(err_id, ec); return (err_id&~3)|1; } } else return 0; } } inline bool is_error_id( std::error_code const & ec ) noexcept { bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat); BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1)); return res; } //////////////////////////////////////// class error_id; namespace leaf_detail { BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; } class error_id { friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept; int value_; BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept: value_(value) { BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); } public: BOOST_LEAF_CONSTEXPR error_id() noexcept: value_(0) { } error_id( std::error_code const & ec ) noexcept: value_(leaf_detail::import_error_code(ec)) { BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1)); } template error_id( Enum e, typename std::enable_if::value, Enum>::type * = 0 ) noexcept: value_(leaf_detail::import_error_code(e)) { } BOOST_LEAF_CONSTEXPR error_id load() const noexcept { return *this; } template BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept { if( int err_id = value() ) { int const unused[ ] = { 42, leaf_detail::load_item::load(err_id, std::forward(item))... }; (void) unused; } return *this; } std::error_code to_error_code() const noexcept { return std::error_code(value_, leaf_detail::get_error_category<>::cat); } BOOST_LEAF_CONSTEXPR int value() const noexcept { if( int v = value_ ) { BOOST_LEAF_ASSERT((v&3)==1); return (v&~3)|1; } else return 0; } BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept { return value_ != 0; } BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept { return a.value_ == b.value_; } BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept { return !(a == b); } BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept { return a.value_ < b.value_; } template friend std::basic_ostream & operator<<( std::basic_ostream & os, error_id x ) { return os << x.value_; } BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept { BOOST_LEAF_ASSERT(file&&*file); BOOST_LEAF_ASSERT(line>0); BOOST_LEAF_ASSERT(function&&*function); BOOST_LEAF_ASSERT(value_); (void) load(e_source_location {file,line,function}); } }; namespace leaf_detail { BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept { BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1); return error_id((err_id&~3)|1); } } inline error_id new_error() noexcept { return leaf_detail::make_error_id(leaf_detail::new_id()); } template inline error_id new_error( Item && ... item ) noexcept { return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward(item)...); } inline error_id current_error() noexcept { return leaf_detail::make_error_id(leaf_detail::current_id()); } //////////////////////////////////////////// class polymorphic_context { protected: polymorphic_context() noexcept = default; ~polymorphic_context() noexcept = default; public: virtual error_id propagate_captured_errors() noexcept = 0; virtual void activate() noexcept = 0; virtual void deactivate() noexcept = 0; virtual void propagate() noexcept = 0; virtual bool is_active() const noexcept = 0; virtual void print( std::ostream & ) const = 0; error_id captured_id_; }; using context_ptr = std::shared_ptr; //////////////////////////////////////////// template class context_activator { context_activator( context_activator const & ) = delete; context_activator & operator=( context_activator const & ) = delete; #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS int const uncaught_exceptions_; #endif Ctx * ctx_; public: explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS uncaught_exceptions_(std::uncaught_exceptions()), #endif ctx_(ctx.is_active() ? 0 : &ctx) { if( ctx_ ) ctx_->activate(); } BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS uncaught_exceptions_(x.uncaught_exceptions_), #endif ctx_(x.ctx_) { x.ctx_ = 0; } BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept { if( !ctx_ ) return; if( ctx_->is_active() ) ctx_->deactivate(); #ifndef BOOST_LEAF_NO_EXCEPTIONS # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS if( std::uncaught_exceptions() > uncaught_exceptions_ ) # else if( std::uncaught_exception() ) # endif ctx_->propagate(); #endif } }; template BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator activate_context(Ctx & ctx) noexcept { return context_activator(ctx); } //////////////////////////////////////////// template struct is_result_type: std::false_type { }; template struct is_result_type: is_result_type { }; } } #undef BOOST_LEAF_THREAD_LOCAL #endif // <<< #include #line 20 "boost/leaf/exception.hpp" #include #define BOOST_LEAF_EXCEPTION ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception #define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::leaf_detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::exception //////////////////////////////////////// namespace boost { namespace leaf { namespace leaf_detail { struct throw_with_loc { char const * const file; int const line; char const * const fn; template [[noreturn]] friend void operator+( throw_with_loc loc, Ex const & ex ) { ex.load_source_location_(loc.file, loc.line, loc.fn); ::boost::leaf::throw_exception(ex); } }; } } } //////////////////////////////////////// namespace boost { namespace leaf { namespace leaf_detail { inline void enforce_std_exception( std::exception const & ) noexcept { } class exception_base { std::shared_ptr auto_id_bump_; public: virtual error_id get_error_id() const noexcept = 0; protected: exception_base(): auto_id_bump_(0, [](void const *) { (void) new_id(); }) { } ~exception_base() noexcept { } }; template class exception: public Ex, public exception_base, public error_id { error_id get_error_id() const noexcept final override { return *this; } public: exception( exception const & ) = default; exception( exception && ) = default; BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept: Ex(std::move(ex)), error_id(id) { enforce_std_exception(*this); } explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept: error_id(id) { enforce_std_exception(*this); } }; template struct at_least_one_derives_from_std_exception; template <> struct at_least_one_derives_from_std_exception<>: std::false_type { }; template struct at_least_one_derives_from_std_exception { constexpr static const bool value = std::is_base_of::value || at_least_one_derives_from_std_exception::value; }; } template inline typename std::enable_if::value, leaf_detail::exception>::type exception( Ex && ex, E && ... e ) noexcept { static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); auto id = leaf::new_error(std::forward(e)...); return leaf_detail::exception(id, std::forward(ex)); } template inline typename std::enable_if::value, leaf_detail::exception>::type exception( E1 && car, E && ... cdr ) noexcept { static_assert(!leaf_detail::at_least_one_derives_from_std_exception::value, "Error objects passed to leaf::exception may not derive from std::exception"); auto id = leaf::new_error(std::forward(car), std::forward(cdr)...); return leaf_detail::exception(id); } inline leaf_detail::exception exception() noexcept { return leaf_detail::exception(leaf::new_error()); } } } #endif // <<< #include #line 20 "boost/leaf/capture.hpp" // >>> #include #line 1 "boost/leaf/on_error.hpp" #ifndef BOOST_LEAF_ON_ERROR_HPP_INCLUDED #define BOOST_LEAF_ON_ERROR_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif namespace boost { namespace leaf { class error_monitor { #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS int const uncaught_exceptions_; #endif int const err_id_; public: error_monitor() noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS uncaught_exceptions_(std::uncaught_exceptions()), #endif err_id_(leaf_detail::current_id()) { } int check_id() const noexcept { int err_id = leaf_detail::current_id(); if( err_id != err_id_ ) return err_id; else { #ifndef BOOST_LEAF_NO_EXCEPTIONS # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS if( std::uncaught_exceptions() > uncaught_exceptions_ ) # else if( std::uncaught_exception() ) # endif return leaf_detail::new_id(); #endif return 0; } } int get_id() const noexcept { int err_id = leaf_detail::current_id(); if( err_id != err_id_ ) return err_id; else return leaf_detail::new_id(); } error_id check() const noexcept { return leaf_detail::make_error_id(check_id()); } error_id assigned_error_id() const noexcept { return leaf_detail::make_error_id(get_id()); } }; //////////////////////////////////////////// namespace leaf_detail { template struct tuple_for_each_preload { BOOST_LEAF_CONSTEXPR static void trigger( Tuple & tup, int err_id ) noexcept { BOOST_LEAF_ASSERT((err_id&3)==1); tuple_for_each_preload::trigger(tup,err_id); std::get(tup).trigger(err_id); } }; template struct tuple_for_each_preload<0, Tuple> { BOOST_LEAF_CONSTEXPR static void trigger( Tuple const &, int ) noexcept { } }; template class preloaded_item { using decay_E = typename std::decay::type; slot * s_; decay_E e_; public: BOOST_LEAF_CONSTEXPR preloaded_item( E && e ): s_(tl_slot_ptr::p), e_(std::forward(e)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { BOOST_LEAF_ASSERT((err_id&3)==1); if( s_ ) { if( !s_->has_value(err_id) ) s_->put(err_id, std::move(e_)); } #if BOOST_LEAF_DIAGNOSTICS else { int c = tl_unexpected_enabled<>::counter; BOOST_LEAF_ASSERT(c>=0); if( c ) load_unexpected(err_id, std::move(e_)); } #endif } }; template class deferred_item { using E = decltype(std::declval()()); slot * s_; F f_; public: BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: s_(tl_slot_ptr::p), f_(std::forward(f)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { BOOST_LEAF_ASSERT((err_id&3)==1); if( s_ ) { if( !s_->has_value(err_id) ) s_->put(err_id, f_()); } #if BOOST_LEAF_DIAGNOSTICS else { int c = tl_unexpected_enabled<>::counter; BOOST_LEAF_ASSERT(c>=0); if( c ) load_unexpected(err_id, std::forward(f_())); } #endif } }; template , int arity = function_traits::arity> class accumulating_item; template class accumulating_item { using E = A0; slot * s_; F f_; public: BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept: s_(tl_slot_ptr::p), f_(std::forward(f)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { BOOST_LEAF_ASSERT((err_id&3)==1); if( s_ ) if( E * e = s_->has_value(err_id) ) (void) f_(*e); else (void) f_(s_->put(err_id, E())); } }; template class preloaded { preloaded & operator=( preloaded const & ) = delete; std::tuple p_; bool moved_; error_monitor id_; public: BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): p_(std::forward(i)...), moved_(false) { } BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept: p_(std::move(x.p_)), moved_(false), id_(std::move(x.id_)) { x.moved_ = true; } ~preloaded() noexcept { if( moved_ ) return; if( auto id = id_.check_id() ) tuple_for_each_preload::trigger(p_,id); } }; template ::arity> struct deduce_item_type; template struct deduce_item_type { using type = preloaded_item; }; template struct deduce_item_type { using type = deferred_item; }; template struct deduce_item_type { using type = accumulating_item; }; } template BOOST_LEAF_NODISCARD BOOST_LEAF_CONSTEXPR inline leaf_detail::preloaded::type...> on_error( Item && ... i ) { return leaf_detail::preloaded::type...>(std::forward(i)...); } } } #endif // <<< #include #line 21 "boost/leaf/capture.hpp" namespace boost { namespace leaf { namespace leaf_detail { template ::value> struct is_result_tag; template struct is_result_tag { }; template struct is_result_tag { }; } #ifdef BOOST_LEAF_NO_EXCEPTIONS namespace leaf_detail { template inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept { auto active_context = activate_context(*ctx); return std::forward(f)(std::forward(a)...); } template inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) noexcept { auto active_context = activate_context(*ctx); if( auto r = std::forward(f)(std::forward(a)...) ) return r; else { ctx->captured_id_ = r.error(); return std::move(ctx); } } template inline decltype(std::declval().get()) future_get_impl(is_result_tag, Future & fut) noexcept { return fut.get(); } template inline decltype(std::declval().get()) future_get_impl(is_result_tag, Future & fut) noexcept { if( auto r = fut.get() ) return r; else return error_id(r.error()); // unloads } } #else namespace leaf_detail { class capturing_exception: public std::exception { std::exception_ptr ex_; context_ptr ctx_; public: capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept: ex_(std::move(ex)), ctx_(std::move(ctx)) { BOOST_LEAF_ASSERT(ex_); BOOST_LEAF_ASSERT(ctx_); BOOST_LEAF_ASSERT(ctx_->captured_id_); } [[noreturn]] void unload_and_rethrow_original_exception() const { BOOST_LEAF_ASSERT(ctx_->captured_id_); auto active_context = activate_context(*ctx_); id_factory<>::current_id = ctx_->captured_id_.value(); std::rethrow_exception(ex_); } template void print( std::basic_ostream & os ) const { ctx_->print(os); } }; template inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); error_monitor cur_err; try { return std::forward(f)(std::forward(a)...); } catch( capturing_exception const & ) { throw; } catch( exception_base const & e ) { ctx->captured_id_ = e.get_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } catch(...) { ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } template inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); error_monitor cur_err; try { if( auto && r = std::forward(f)(std::forward(a)...) ) return std::move(r); else { ctx->captured_id_ = r.error(); return std::move(ctx); } } catch( capturing_exception const & ) { throw; } catch( exception_base const & e ) { ctx->captured_id_ = e.get_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } catch(...) { ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } template inline decltype(std::declval().get()) future_get_impl(is_result_tag, Future & fut ) { try { return fut.get(); } catch( capturing_exception const & cap ) { cap.unload_and_rethrow_original_exception(); } } template inline decltype(std::declval().get()) future_get_impl(is_result_tag, Future & fut ) { try { if( auto r = fut.get() ) return r; else return error_id(r.error()); // unloads } catch( capturing_exception const & cap ) { cap.unload_and_rethrow_original_exception(); } } } #endif template inline decltype(std::declval()(std::forward(std::declval())...)) capture(context_ptr && ctx, F && f, A... a) { using namespace leaf_detail; return capture_impl(is_result_tag()(std::forward(std::declval())...))>(), std::move(ctx), std::forward(f), std::forward(a)...); } template inline decltype(std::declval().get()) future_get( Future & fut ) { using namespace leaf_detail; return future_get_impl(is_result_tag().get())>(), fut); } //////////////////////////////////////// #ifndef BOOST_LEAF_NO_EXCEPTIONS template class result; namespace leaf_detail { inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> ) { return leaf::new_error(std::current_exception()); } template inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list ) { if( Ex1 const * p = dynamic_cast(&ex) ) return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }).load(*p); else return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list{ }); } template struct deduce_exception_to_result_return_type_impl { using type = result; }; template struct deduce_exception_to_result_return_type_impl> { using type = result; }; template using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl::type; } template inline leaf_detail::deduce_exception_to_result_return_type> exception_to_result( F && f ) noexcept { try { return std::forward(f)(); } catch( std::exception const & ex ) { return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list()); } catch(...) { return leaf::new_error(std::current_exception()); } } #endif } } #endif // <<< #include #line 10 "../../include/boost/leaf/detail/all.hpp" // >>> #include #line 1 "boost/leaf/common.hpp" #ifndef BOOST_LEAF_COMMON_HPP_INCLUDED #define BOOST_LEAF_COMMON_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif #include #include #ifdef _WIN32 # include # include #ifdef min # undef min #endif #ifdef max # undef max #endif #endif namespace boost { namespace leaf { struct e_api_function { char const * value; }; struct e_file_name { std::string value; }; struct e_errno { int value; template friend std::basic_ostream & operator<<( std::basic_ostream & os, e_errno const & err ) { return os << type() << ": " << err.value << ", \"" << std::strerror(err.value) << '"'; } }; struct e_type_info_name { char const * value; }; struct e_at_line { int value; }; namespace windows { struct e_LastError { unsigned value; #ifdef _WIN32 template friend std::basic_ostream & operator<<( std::basic_ostream os, e_LastError const & err ) { struct msg_buf { LPVOID * p; msg_buf(): p(0) { } ~msg_buf() noexcept { if(p) LocalFree(p); } }; msg_buf mb; if( FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, err.value, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPSTR)&mb.p, 0, 0) ) { BOOST_LEAF_ASSERT(mb.p != 0); char * z = std::strchr((LPSTR)mb.p,0); if( z[-1] == '\n' ) *--z = 0; if( z[-1] == '\r' ) *--z = 0; return os << type() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"'; } return os; } #else // TODO : Other platforms #endif }; } } } #endif // <<< #include #line 11 "../../include/boost/leaf/detail/all.hpp" // >>> #include #line 1 "boost/leaf/context.hpp" #ifndef BOOST_LEAF_CONTEXT_HPP_INCLUDED #define BOOST_LEAF_CONTEXT_HPP_INCLUDED // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_LEAF_ENABLE_WARNINGS # if defined(__clang__) # pragma clang system_header # elif (__GNUC__*100+__GNUC_MINOR__>301) # pragma GCC system_header # elif defined(_MSC_VER) # pragma warning(push,1) # endif #endif namespace boost { namespace leaf { class error_info; class diagnostic_info; class verbose_diagnostic_info; template struct is_predicate: std::false_type { }; namespace leaf_detail { template struct is_exception: std::is_base_of::type> { }; template struct handler_argument_traits; template ::value> struct handler_argument_traits_defaults; template struct handler_argument_traits_defaults { using error_type = typename std::decay::type; constexpr static bool always_available = false; template BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept; template BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept; template BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept { return *check(tup, ei); } static_assert(!is_predicate::value, "Handlers must take predicate arguments by value"); static_assert(!std::is_same::value, "Handlers must take leaf::error_info arguments by const &"); static_assert(!std::is_same::value, "Handlers must take leaf::diagnostic_info arguments by const &"); static_assert(!std::is_same::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &"); }; template struct handler_argument_traits_defaults: handler_argument_traits { using base = handler_argument_traits; static_assert(!base::always_available, "Predicates can't use types that are always_available"); template BOOST_LEAF_CONSTEXPR static bool check( Tup const & tup, error_info const & ei ) noexcept { auto e = base::check(tup, ei); return e && Pred::evaluate(*e); }; template BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept { return Pred{*base::check(tup, ei)}; } }; template struct handler_argument_always_available { using error_type = E; constexpr static bool always_available = true; template BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept { return true; }; }; template struct handler_argument_traits: handler_argument_traits_defaults { }; template <> struct handler_argument_traits { using error_type = void; constexpr static bool always_available = false; template BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept; }; template struct handler_argument_traits { static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments"); }; template struct handler_argument_traits: handler_argument_always_available::type> { template BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept { return handler_argument_traits_defaults::check(tup, ei); } }; template <> struct handler_argument_traits: handler_argument_always_available { template BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept { return ei; } }; template struct handler_argument_traits_require_by_value { static_assert(sizeof(E) == 0, "Error handlers must take this type by value"); }; } //////////////////////////////////////// namespace leaf_detail { template struct tuple_for_each { BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); tuple_for_each::activate(tup); std::get(tup).activate(); } BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); std::get(tup).deactivate(); tuple_for_each::deactivate(tup); } BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); auto & sl = std::get(tup); sl.propagate(); tuple_for_each::propagate(tup); } BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept { static_assert(!std::is_same(tup))>::type>::value, "Bug in LEAF: context type deduction"); auto & sl = std::get(tup); if( sl.has_value(err_id) ) load_slot(err_id, std::move(sl).value(err_id)); tuple_for_each::propagate_captured(tup, err_id); } static void print( std::ostream & os, void const * tup, int key_to_print ) { BOOST_LEAF_ASSERT(tup != 0); tuple_for_each::print(os, tup, key_to_print); std::get(*static_cast(tup)).print(os, key_to_print); } }; template struct tuple_for_each<0, Tuple> { BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { } BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { } BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { } BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { } static void print( std::ostream &, void const *, int ) { } }; } //////////////////////////////////////////// #if BOOST_LEAF_DIAGNOSTICS namespace leaf_detail { template struct requires_unexpected { constexpr static bool value = false; }; template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; template struct requires_unexpected { constexpr static bool value = requires_unexpected::value; }; template <> struct requires_unexpected { constexpr static bool value = true; }; template <> struct requires_unexpected { constexpr static bool value = true; }; template struct unexpected_requested; template