Back to home page

EIC code displayed by LXR

 
 

    


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