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