Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:44:53

0001 #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0002 #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0003 
0004 // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
0005 
0006 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0007 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #include <boost/leaf/config.hpp>
0010 #include <boost/leaf/error.hpp>
0011 #include <exception>
0012 
0013 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0014 
0015 namespace boost
0016 {
0017     [[noreturn]] void throw_exception( std::exception const & ); // user defined
0018 }
0019 
0020 namespace boost { namespace leaf {
0021 
0022 namespace leaf_detail
0023 {
0024     template <class T>
0025     [[noreturn]] void throw_exception_impl( T && e )
0026     {
0027         ::boost::throw_exception(std::move(e));
0028     }
0029 
0030     class BOOST_LEAF_SYMBOL_VISIBLE exception_base
0031     {
0032     public:
0033 
0034         virtual error_id get_error_id() const noexcept = 0;
0035 
0036     protected:
0037 
0038         exception_base() noexcept { }
0039         ~exception_base() noexcept { }
0040     };
0041 }
0042 
0043 } }
0044 
0045 #else
0046 
0047 #include <memory>
0048 
0049 namespace boost { namespace leaf {
0050 
0051 namespace leaf_detail
0052 {
0053     template <class T>
0054     [[noreturn]] void throw_exception_impl( T && e )
0055     {
0056         throw std::move(e);
0057     }
0058 
0059     class BOOST_LEAF_SYMBOL_VISIBLE exception_base
0060     {
0061         std::shared_ptr<void const> auto_id_bump_;
0062 
0063     public:
0064 
0065         virtual error_id get_error_id() const noexcept = 0;
0066 
0067     protected:
0068 
0069         exception_base():
0070             auto_id_bump_(nullptr, [](void const *) { (void) new_id(); })
0071         {
0072         }
0073 
0074         ~exception_base() noexcept { }
0075     };
0076 }
0077 
0078 } }
0079 
0080 #endif
0081 
0082 ////////////////////////////////////////
0083 
0084 #define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::leaf_detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::leaf_detail::make_exception
0085 
0086 namespace boost { namespace leaf {
0087 
0088 namespace leaf_detail
0089 {
0090     struct throw_with_loc
0091     {
0092         char const * const file;
0093         int const line;
0094         char const * const fn;
0095 
0096         template <class Ex>
0097         [[noreturn]] friend void operator+( throw_with_loc loc, Ex && ex )
0098         {
0099             ex.load_source_location_(loc.file, loc.line, loc.fn);
0100             ::boost::leaf::leaf_detail::throw_exception_impl(std::move(ex));
0101         }
0102     };
0103 }
0104 
0105 } }
0106 
0107 ////////////////////////////////////////
0108 
0109 namespace boost { namespace leaf {
0110 
0111 namespace leaf_detail
0112 {
0113     inline void enforce_std_exception( std::exception const & ) noexcept { }
0114 
0115     template <class Ex>
0116     class BOOST_LEAF_SYMBOL_VISIBLE exception:
0117         public Ex,
0118         public exception_base,
0119         public error_id
0120     {
0121         error_id get_error_id() const noexcept final override
0122         {
0123             return *this;
0124         }
0125 
0126     public:
0127 
0128         exception( exception const & ) = default;
0129         exception( exception && ) = default;
0130 
0131         BOOST_LEAF_CONSTEXPR exception( error_id id, Ex const & ex ) noexcept:
0132             Ex(ex),
0133             error_id(id)
0134         {
0135             enforce_std_exception(*this);
0136         }
0137 
0138         BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept:
0139             Ex(std::move(ex)),
0140             error_id(id)
0141         {
0142             enforce_std_exception(*this);
0143         }
0144 
0145         explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept:
0146             error_id(id)
0147         {
0148             enforce_std_exception(*this);
0149         }
0150     };
0151 
0152     template <class... T>
0153     struct at_least_one_derives_from_std_exception;
0154 
0155     template <>
0156     struct at_least_one_derives_from_std_exception<>: std::false_type { };
0157 
0158     template <class T, class... Rest>
0159     struct at_least_one_derives_from_std_exception<T, Rest...>
0160     {
0161         constexpr static const bool value = std::is_base_of<std::exception,typename std::remove_reference<T>::type>::value || at_least_one_derives_from_std_exception<Rest...>::value;
0162     };
0163 
0164     template <class Ex, class... E>
0165     inline
0166     typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, exception<typename std::remove_reference<Ex>::type>>::type
0167     make_exception( error_id err, Ex && ex, E && ... e ) noexcept
0168     {
0169         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0170         return exception<typename std::remove_reference<Ex>::type>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0171     }
0172 
0173     template <class E1, class... E>
0174     inline
0175     typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0176     make_exception( error_id err, E1 && car, E && ... cdr ) noexcept
0177     {
0178         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0179         return exception<std::exception>( err.load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0180     }
0181 
0182     inline exception<std::exception> make_exception( error_id err ) noexcept
0183     {
0184         return exception<std::exception>(err);
0185     }
0186 
0187     template <class Ex, class... E>
0188     inline
0189     typename std::enable_if<std::is_base_of<std::exception,typename std::remove_reference<Ex>::type>::value, exception<typename std::remove_reference<Ex>::type>>::type
0190     make_exception( Ex && ex, E && ... e ) noexcept
0191     {
0192         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0193         return exception<typename std::remove_reference<Ex>::type>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0194     }
0195 
0196     template <class E1, class... E>
0197     inline
0198     typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0199     make_exception( E1 && car, E && ... cdr ) noexcept
0200     {
0201         static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0202         return exception<std::exception>( new_error().load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0203     }
0204 
0205     inline exception<std::exception> make_exception() noexcept
0206     {
0207         return exception<std::exception>(leaf::new_error());
0208     }
0209 }
0210 
0211 template <class... E>
0212 [[noreturn]] void throw_exception( E && ... e )
0213 {
0214     // Warning: setting a breakpoint here will not intercept exceptions thrown
0215     // via BOOST_LEAF_THROW_EXCEPTION or originating in the few other throw
0216     // points elsewhere in LEAF. To intercept all of those exceptions as well,
0217     // set a breakpoint inside boost::leaf::leaf_detail::throw_exception_impl.
0218     leaf_detail::throw_exception_impl(leaf_detail::make_exception(std::forward<E>(e)...));
0219 }
0220 
0221 ////////////////////////////////////////
0222 
0223 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0224 
0225 template <class T>
0226 class result;
0227 
0228 namespace leaf_detail
0229 {
0230     inline error_id catch_exceptions_helper( std::exception const &, leaf_detail_mp11::mp_list<> )
0231     {
0232         return leaf::new_error(std::current_exception());
0233     }
0234 
0235     template <class Ex1, class... Ex>
0236     inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
0237     {
0238         if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
0239             return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
0240         else
0241             return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
0242     }
0243 
0244     template <class T>
0245     struct deduce_exception_to_result_return_type_impl
0246     {
0247         using type = result<T>;
0248     };
0249 
0250     template <class T>
0251     struct deduce_exception_to_result_return_type_impl<result<T>>
0252     {
0253         using type = result<T>;
0254     };
0255 
0256     template <class T>
0257     using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
0258 }
0259 
0260 template <class... Ex, class F>
0261 inline
0262 leaf_detail::deduce_exception_to_result_return_type<leaf_detail::fn_return_type<F>>
0263 exception_to_result( F && f ) noexcept
0264 {
0265     try
0266     {
0267         return std::forward<F>(f)();
0268     }
0269     catch( std::exception const & ex )
0270     {
0271         return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
0272     }
0273     catch(...)
0274     {
0275         return leaf::new_error(std::current_exception());
0276     }
0277 }
0278 
0279 #endif
0280 
0281 } }
0282 
0283 #endif