File indexing completed on 2025-09-15 08:39:09
0001 #ifndef BOOST_LEAF_ON_ERROR_HPP_INCLUDED
0002 #define BOOST_LEAF_ON_ERROR_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/leaf/config.hpp>
0009 #include <boost/leaf/error.hpp>
0010
0011 namespace boost { namespace leaf {
0012
0013 class error_monitor
0014 {
0015 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
0016 int const uncaught_exceptions_;
0017 #endif
0018 int const err_id_;
0019
0020 public:
0021
0022 error_monitor() noexcept:
0023 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
0024 uncaught_exceptions_(std::uncaught_exceptions()),
0025 #endif
0026 err_id_(detail::current_id())
0027 {
0028 }
0029
0030 int check_id() const noexcept
0031 {
0032 int err_id = detail::current_id();
0033 if( err_id != err_id_ )
0034 return err_id;
0035 else
0036 {
0037 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0038 # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
0039 if( std::uncaught_exceptions() > uncaught_exceptions_ )
0040 # else
0041 if( std::uncaught_exception() )
0042 # endif
0043 return detail::new_id();
0044 #endif
0045 return 0;
0046 }
0047 }
0048
0049 int get_id() const noexcept
0050 {
0051 int err_id = detail::current_id();
0052 if( err_id != err_id_ )
0053 return err_id;
0054 else
0055 return detail::new_id();
0056 }
0057
0058 error_id check() const noexcept
0059 {
0060 return detail::make_error_id(check_id());
0061 }
0062
0063 error_id assigned_error_id() const noexcept
0064 {
0065 return detail::make_error_id(get_id());
0066 }
0067 };
0068
0069
0070
0071 namespace detail
0072 {
0073 template <int I, class Tup>
0074 struct tuple_for_each_preload
0075 {
0076 BOOST_LEAF_CONSTEXPR static void trigger( Tup & tup, int err_id ) noexcept
0077 {
0078 BOOST_LEAF_ASSERT((err_id&3) == 1);
0079 tuple_for_each_preload<I-1,Tup>::trigger(tup,err_id);
0080 std::get<I-1>(tup).trigger(err_id);
0081 }
0082 };
0083
0084 template <class Tup>
0085 struct tuple_for_each_preload<0, Tup>
0086 {
0087 BOOST_LEAF_CONSTEXPR static void trigger( Tup const &, int ) noexcept { }
0088 };
0089
0090 template <class E>
0091 class preloaded_item
0092 {
0093 using decay_E = typename std::decay<E>::type;
0094 decay_E e_;
0095
0096 public:
0097
0098 BOOST_LEAF_CONSTEXPR preloaded_item( E && e ):
0099 e_(std::forward<E>(e))
0100 {
0101 }
0102
0103 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
0104 {
0105 (void) load_slot<true>(err_id, std::move(e_));
0106 }
0107 };
0108
0109 template <class F, class ReturnType = typename function_traits<F>::return_type>
0110 class deferred_item
0111 {
0112 F f_;
0113
0114 public:
0115
0116 BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept:
0117 f_(std::forward<F>(f))
0118 {
0119 }
0120
0121 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
0122 {
0123 (void) load_slot_deferred<true>(err_id, f_);
0124 }
0125 };
0126
0127 template <class F>
0128 class deferred_item<F, void>
0129 {
0130 F f_;
0131
0132 public:
0133
0134 BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept:
0135 f_(std::forward<F>(f))
0136 {
0137 }
0138
0139 BOOST_LEAF_CONSTEXPR void trigger( int ) noexcept
0140 {
0141 f_();
0142 }
0143 };
0144
0145 template <class F, class A0 = fn_arg_type<F,0>, int arity = function_traits<F>::arity>
0146 class accumulating_item;
0147
0148 template <class F, class A0>
0149 class accumulating_item<F, A0 &, 1>
0150 {
0151 F f_;
0152
0153 public:
0154
0155 BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept:
0156 f_(std::forward<F>(f))
0157 {
0158 }
0159
0160 BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept
0161 {
0162 load_slot_accumulate<true>(err_id, std::move(f_));
0163 }
0164 };
0165
0166 template <class... Item>
0167 class preloaded
0168 {
0169 preloaded & operator=( preloaded const & ) = delete;
0170
0171 std::tuple<Item...> p_;
0172 bool moved_;
0173 error_monitor id_;
0174
0175 public:
0176
0177 BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ):
0178 p_(std::forward<Item>(i)...),
0179 moved_(false)
0180 {
0181 }
0182
0183 BOOST_LEAF_CONSTEXPR preloaded( preloaded && x ) noexcept:
0184 p_(std::move(x.p_)),
0185 moved_(false),
0186 id_(std::move(x.id_))
0187 {
0188 x.moved_ = true;
0189 }
0190
0191 ~preloaded() noexcept
0192 {
0193 if( moved_ )
0194 return;
0195 if( auto id = id_.check_id() )
0196 tuple_for_each_preload<sizeof...(Item),decltype(p_)>::trigger(p_,id);
0197 }
0198 };
0199
0200 template <class T, int arity = function_traits<T>::arity>
0201 struct deduce_item_type;
0202
0203 template <class T>
0204 struct deduce_item_type<T, -1>
0205 {
0206 using type = preloaded_item<T>;
0207 };
0208
0209 template <class F>
0210 struct deduce_item_type<F, 0>
0211 {
0212 using type = deferred_item<F>;
0213 };
0214
0215 template <class F>
0216 struct deduce_item_type<F, 1>
0217 {
0218 using type = accumulating_item<F>;
0219 };
0220 }
0221
0222 template <class... Item>
0223 BOOST_LEAF_ATTRIBUTE_NODISCARD BOOST_LEAF_CONSTEXPR inline
0224 detail::preloaded<typename detail::deduce_item_type<Item>::type...>
0225 on_error( Item && ... i )
0226 {
0227 return detail::preloaded<typename detail::deduce_item_type<Item>::type...>(std::forward<Item>(i)...);
0228 }
0229
0230 } }
0231
0232 #endif