File indexing completed on 2025-09-16 08:37:42
0001 #ifndef BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0002 #define BOOST_LEAF_EXCEPTION_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/leaf/config.hpp>
0009 #include <boost/leaf/error.hpp>
0010 #include <exception>
0011 #include <typeinfo>
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 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
0031 } }
0032
0033 #else
0034
0035 namespace boost { namespace leaf {
0036
0037 namespace detail
0038 {
0039 template <class T>
0040 [[noreturn]] void throw_exception_impl( T && e )
0041 {
0042 throw std::move(e);
0043 }
0044 }
0045
0046 } }
0047
0048 #endif
0049
0050
0051
0052 #define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::detail::make_exception
0053
0054 namespace boost { namespace leaf {
0055
0056 namespace detail
0057 {
0058 struct throw_with_loc
0059 {
0060 char const * const file;
0061 int const line;
0062 char const * const fn;
0063
0064 template <class Ex>
0065 [[noreturn]] friend void operator+( throw_with_loc loc, Ex && ex )
0066 {
0067 ex.load_source_location_(loc.file, loc.line, loc.fn);
0068 ::boost::leaf::detail::throw_exception_impl(std::move(ex));
0069 }
0070 };
0071 }
0072
0073
0074
0075 namespace detail
0076 {
0077 inline void enforce_std_exception( std::exception const & ) noexcept { }
0078
0079 template <class Ex>
0080 class BOOST_LEAF_SYMBOL_VISIBLE exception:
0081 public Ex,
0082 public exception_base,
0083 public error_id
0084 {
0085 mutable bool clear_current_error_;
0086
0087 bool is_current_exception() const noexcept
0088 {
0089 return tls::read_uint<detail::tls_tag_id_factory_current_id>() == unsigned(error_id::value());
0090 }
0091
0092 error_id get_error_id() const noexcept final override
0093 {
0094 clear_current_error_ = false;
0095 return *this;
0096 }
0097
0098 #if BOOST_LEAF_CFG_DIAGNOSTICS && !defined(BOOST_LEAF_NO_EXCEPTIONS)
0099 void print_type_name(std::ostream & os) const final override
0100 {
0101 detail::demangle_and_print(os, typeid(Ex).name());
0102 }
0103 #endif
0104
0105 public:
0106
0107 exception( exception const & other ):
0108 Ex(other),
0109 exception_base(other),
0110 error_id(other),
0111 clear_current_error_(other.clear_current_error_)
0112 {
0113 other.clear_current_error_ = false;
0114 }
0115
0116 exception( exception && other ) noexcept:
0117 Ex(std::move(other)),
0118 exception_base(std::move(other)),
0119 error_id(std::move(other)),
0120 clear_current_error_(std::move(other.clear_current_error_))
0121 {
0122 other.clear_current_error_ = false;
0123 }
0124
0125 exception( error_id id, Ex const & ex ) noexcept:
0126 Ex(ex),
0127 error_id(id),
0128 clear_current_error_(true)
0129 {
0130 enforce_std_exception(*this);
0131 }
0132
0133 exception( error_id id, Ex && ex ) noexcept:
0134 Ex(std::move(ex)),
0135 error_id(id),
0136 clear_current_error_(true)
0137 {
0138 enforce_std_exception(*this);
0139 }
0140
0141 explicit exception( error_id id ) noexcept:
0142 error_id(id),
0143 clear_current_error_(true)
0144 {
0145 enforce_std_exception(*this);
0146 }
0147
0148 ~exception() noexcept
0149 {
0150 if( clear_current_error_ && is_current_exception() )
0151 tls::write_uint<detail::tls_tag_id_factory_current_id>(0);
0152 }
0153 };
0154
0155 template <class... T>
0156 struct at_least_one_derives_from_std_exception;
0157
0158 template <>
0159 struct at_least_one_derives_from_std_exception<>: std::false_type { };
0160
0161 template <class T, class... Rest>
0162 struct at_least_one_derives_from_std_exception<T, Rest...>
0163 {
0164 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;
0165 };
0166
0167 template <class Ex, class... E>
0168 inline
0169 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
0170 make_exception( error_id err, Ex && ex, E && ... e ) noexcept
0171 {
0172 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0173 return exception<typename std::remove_reference<Ex>::type>( err.load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0174 }
0175
0176 template <class E1, class... E>
0177 inline
0178 typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0179 make_exception( error_id err, E1 && car, E && ... cdr ) noexcept
0180 {
0181 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0182 return exception<std::exception>( err.load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0183 }
0184
0185 inline exception<std::exception> make_exception( error_id err ) noexcept
0186 {
0187 return exception<std::exception>(err);
0188 }
0189
0190 template <class Ex, class... E>
0191 inline
0192 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
0193 make_exception( Ex && ex, E && ... e ) noexcept
0194 {
0195 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0196 return exception<typename std::remove_reference<Ex>::type>( new_error().load(std::forward<E>(e)...), std::forward<Ex>(ex) );
0197 }
0198
0199 template <class E1, class... E>
0200 inline
0201 typename std::enable_if<!std::is_base_of<std::exception,typename std::remove_reference<E1>::type>::value, exception<std::exception>>::type
0202 make_exception( E1 && car, E && ... cdr ) noexcept
0203 {
0204 static_assert(!at_least_one_derives_from_std_exception<E...>::value, "Error objects passed to leaf::exception may not derive from std::exception");
0205 return exception<std::exception>( new_error().load(std::forward<E1>(car), std::forward<E>(cdr)...) );
0206 }
0207
0208 inline exception<std::exception> make_exception() noexcept
0209 {
0210 return exception<std::exception>(leaf::new_error());
0211 }
0212 }
0213
0214 template <class... E>
0215 [[noreturn]] void throw_exception( E && ... e )
0216 {
0217
0218
0219
0220
0221 detail::throw_exception_impl(detail::make_exception(std::forward<E>(e)...));
0222 }
0223
0224
0225
0226 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0227
0228 template <class T>
0229 class BOOST_LEAF_SYMBOL_VISIBLE result;
0230
0231 namespace detail
0232 {
0233 inline error_id catch_exceptions_helper( std::exception const &, leaf_detail_mp11::mp_list<> )
0234 {
0235 return leaf::new_error(std::current_exception());
0236 }
0237
0238 template <class Ex1, class... Ex>
0239 inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
0240 {
0241 if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
0242 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
0243 else
0244 return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
0245 }
0246
0247 template <class T>
0248 struct deduce_exception_to_result_return_type_impl
0249 {
0250 using type = result<T>;
0251 };
0252
0253 template <class T>
0254 struct deduce_exception_to_result_return_type_impl<result<T>>
0255 {
0256 using type = result<T>;
0257 };
0258
0259 template <class T>
0260 using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
0261 }
0262
0263 template <class... Ex, class F>
0264 inline
0265 detail::deduce_exception_to_result_return_type<detail::fn_return_type<F>>
0266 exception_to_result( F && f ) noexcept
0267 {
0268 try
0269 {
0270 return std::forward<F>(f)();
0271 }
0272 catch( std::exception const & ex )
0273 {
0274 return detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
0275 }
0276 catch(...)
0277 {
0278 return leaf::new_error(std::current_exception());
0279 }
0280 }
0281
0282 #endif
0283
0284 } }
0285
0286 #endif