File indexing completed on 2025-07-05 08:36:32
0001 #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0002 #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0003
0004
0005
0006
0007
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 & );
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 namespace leaf_detail
0108 {
0109 inline void enforce_std_exception( std::exception const & ) noexcept { }
0110
0111 template <class Ex>
0112 class BOOST_LEAF_SYMBOL_VISIBLE exception:
0113 public Ex,
0114 public exception_base,
0115 public error_id
0116 {
0117 error_id get_error_id() const noexcept final override
0118 {
0119 return *this;
0120 }
0121
0122 public:
0123
0124 exception( exception const & ) = default;
0125 exception( exception && ) = default;
0126
0127 BOOST_LEAF_CONSTEXPR exception( error_id id, Ex const & ex ) noexcept:
0128 Ex(ex),
0129 error_id(id)
0130 {
0131 enforce_std_exception(*this);
0132 }
0133
0134 BOOST_LEAF_CONSTEXPR exception( error_id id, Ex && ex ) noexcept:
0135 Ex(std::move(ex)),
0136 error_id(id)
0137 {
0138 enforce_std_exception(*this);
0139 }
0140
0141 explicit BOOST_LEAF_CONSTEXPR exception( error_id id ) noexcept:
0142 error_id(id)
0143 {
0144 enforce_std_exception(*this);
0145 }
0146 };
0147
0148 template <class... T>
0149 struct at_least_one_derives_from_std_exception;
0150
0151 template <>
0152 struct at_least_one_derives_from_std_exception<>: std::false_type { };
0153
0154 template <class T, class... Rest>
0155 struct at_least_one_derives_from_std_exception<T, Rest...>
0156 {
0157 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;
0158 };
0159
0160 template <class Ex, class... E>
0161 inline
0162 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
0163 make_exception( error_id err, Ex && ex, E && ... e ) noexcept
0164 {
0165 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0166 return exception<typename std::remove_reference<Ex>::type>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0167 }
0168
0169 template <class E1, class... E>
0170 inline
0171 typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0172 make_exception( error_id err, E1 && car, E && ... cdr ) noexcept
0173 {
0174 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0175 return exception<std::exception>( err.load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0176 }
0177
0178 inline exception<std::exception> make_exception( error_id err ) noexcept
0179 {
0180 return exception<std::exception>(err);
0181 }
0182
0183 template <class Ex, class... E>
0184 inline
0185 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
0186 make_exception( Ex && ex, E && ... e ) noexcept
0187 {
0188 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0189 return exception<typename std::remove_reference<Ex>::type>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0190 }
0191
0192 template <class E1, class... E>
0193 inline
0194 typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0195 make_exception( E1 && car, E && ... cdr ) noexcept
0196 {
0197 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0198 return exception<std::exception>( new_error().load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0199 }
0200
0201 inline exception<std::exception> make_exception() noexcept
0202 {
0203 return exception<std::exception>(leaf::new_error());
0204 }
0205 }
0206
0207 template <class... E>
0208 [[noreturn]] void throw_exception( E && ... e )
0209 {
0210
0211
0212
0213
0214 leaf_detail::throw_exception_impl(leaf_detail::make_exception(std::forward<E>(e)...));
0215 }
0216
0217
0218
0219 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0220
0221 template <class T>
0222 class BOOST_LEAF_SYMBOL_VISIBLE result;
0223
0224 namespace leaf_detail
0225 {
0226 inline error_id catch_exceptions_helper( std::exception const &, leaf_detail_mp11::mp_list<> )
0227 {
0228 return leaf::new_error(std::current_exception());
0229 }
0230
0231 template <class Ex1, class... Ex>
0232 inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
0233 {
0234 if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
0235 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
0236 else
0237 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
0238 }
0239
0240 template <class T>
0241 struct deduce_exception_to_result_return_type_impl
0242 {
0243 using type = result<T>;
0244 };
0245
0246 template <class T>
0247 struct deduce_exception_to_result_return_type_impl<result<T>>
0248 {
0249 using type = result<T>;
0250 };
0251
0252 template <class T>
0253 using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
0254 }
0255
0256 template <class... Ex, class F>
0257 inline
0258 leaf_detail::deduce_exception_to_result_return_type<leaf_detail::fn_return_type<F>>
0259 exception_to_result( F && f ) noexcept
0260 {
0261 try
0262 {
0263 return std::forward<F>(f)();
0264 }
0265 catch( std::exception const & ex )
0266 {
0267 return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
0268 }
0269 catch(...)
0270 {
0271 return leaf::new_error(std::current_exception());
0272 }
0273 }
0274
0275 #endif
0276
0277 } }
0278
0279 #endif