Back to home page

EIC code displayed by LXR

 
 

    


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 // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
0005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // BOOST_LEAF_ON_ERROR_HPP_INCLUDED