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
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
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
0215
0216
0217
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