Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:37:25

0001 #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED
0002 #define BOOST_LEAF_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/detail/optional.hpp>
0011 #include <boost/leaf/detail/function_traits.hpp>
0012 #include <boost/leaf/detail/capture_list.hpp>
0013 #include <boost/leaf/detail/print.hpp>
0014 
0015 #if BOOST_LEAF_CFG_DIAGNOSTICS
0016 #   include <ostream>
0017 #endif
0018 
0019 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0020 #   include <system_error>
0021 #endif
0022 
0023 #if BOOST_LEAF_CFG_CAPTURE
0024 #   include <memory>
0025 #endif
0026 
0027 #define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y
0028 #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y)
0029 #define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__)
0030 
0031 #define BOOST_LEAF_ASSIGN(v,r)\
0032     auto && BOOST_LEAF_TMP = r;\
0033     static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
0034         "BOOST_LEAF_ASSIGN/BOOST_LEAF_AUTO requires a result object as the second argument (see is_result_type)");\
0035     if( !BOOST_LEAF_TMP )\
0036         return BOOST_LEAF_TMP.error();\
0037     v = std::forward<decltype(BOOST_LEAF_TMP)>(BOOST_LEAF_TMP).value()
0038 
0039 #define BOOST_LEAF_AUTO(v, r)\
0040     BOOST_LEAF_ASSIGN(auto v, r)
0041 
0042 #if BOOST_LEAF_CFG_GNUC_STMTEXPR
0043 
0044 #define BOOST_LEAF_CHECK(r)\
0045     ({\
0046         auto && BOOST_LEAF_TMP = (r);\
0047         static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
0048             "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
0049         if( !BOOST_LEAF_TMP )\
0050             return BOOST_LEAF_TMP.error();\
0051         std::move(BOOST_LEAF_TMP);\
0052     }).value()
0053 
0054 #else
0055 
0056 #define BOOST_LEAF_CHECK(r)\
0057     {\
0058         auto && BOOST_LEAF_TMP = (r);\
0059         static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
0060             "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
0061         if( !BOOST_LEAF_TMP )\
0062             return BOOST_LEAF_TMP.error();\
0063     }
0064 
0065 #endif
0066 
0067 #define BOOST_LEAF_NEW_ERROR ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error
0068 
0069 namespace boost { namespace leaf {
0070 
0071 struct BOOST_LEAF_SYMBOL_VISIBLE e_source_location
0072 {
0073     char const * file;
0074     int line;
0075     char const * function;
0076 
0077     template <class CharT, class Traits>
0078     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, e_source_location const & x )
0079     {
0080         return os << leaf::type<e_source_location>() << ": " << x.file << '(' << x.line << ") in function " << x.function;
0081     }
0082 };
0083 
0084 ////////////////////////////////////////
0085 
0086 class BOOST_LEAF_SYMBOL_VISIBLE error_id;
0087 
0088 namespace leaf_detail
0089 {
0090     template <class E>
0091     class BOOST_LEAF_SYMBOL_VISIBLE slot:
0092         optional<E>
0093     {
0094         slot( slot const & ) = delete;
0095         slot & operator=( slot const & ) = delete;
0096 
0097         using impl = optional<E>;
0098         slot<E> * prev_;
0099 
0100     public:
0101 
0102         BOOST_LEAF_CONSTEXPR slot() noexcept:
0103             prev_(nullptr)
0104         {
0105         }
0106 
0107         BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept:
0108             optional<E>(std::move(x)),
0109             prev_(nullptr)
0110         {
0111             BOOST_LEAF_ASSERT(x.prev_==nullptr);
0112         }
0113 
0114         ~slot() noexcept
0115         {
0116             BOOST_LEAF_ASSERT(tls::read_ptr<slot<E>>() != this);
0117         }
0118 
0119         void activate() noexcept
0120         {
0121             prev_ = tls::read_ptr<slot<E>>();
0122             tls::write_ptr<slot<E>>(this);
0123         }
0124 
0125         void deactivate() const noexcept
0126         {
0127             tls::write_ptr<slot<E>>(prev_);
0128         }
0129 
0130         void unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE);
0131 
0132         template <class CharT, class Traits>
0133         void print( std::basic_ostream<CharT, Traits> & os, int err_id_to_print ) const
0134         {
0135             if( !diagnostic<E>::is_invisible )
0136                 if( int k = this->key() )
0137                 {
0138                     if( err_id_to_print )
0139                     {
0140                         if( err_id_to_print!=k )
0141                             return;
0142                     }
0143                     else
0144                         os << '[' << k << "] ";
0145                     diagnostic<E>::print(os, value(k));
0146                     os << '\n';
0147                 }
0148         }
0149 
0150         using impl::load;
0151         using impl::has_value;
0152         using impl::value;
0153     };
0154 }
0155 
0156 ////////////////////////////////////////
0157 
0158 #if BOOST_LEAF_CFG_CAPTURE
0159 
0160 namespace leaf_detail
0161 {
0162     class BOOST_LEAF_SYMBOL_VISIBLE dynamic_allocator:
0163         capture_list
0164     {
0165         dynamic_allocator( dynamic_allocator const & ) = delete;
0166         dynamic_allocator & operator=( dynamic_allocator const & ) = delete;
0167 
0168         class capturing_node:
0169             public capture_list::node
0170         {
0171         protected:
0172             BOOST_LEAF_CONSTEXPR explicit capturing_node( capture_list::node * * & last ) noexcept:
0173                 node(last)
0174             {
0175                 BOOST_LEAF_ASSERT(last == &next_);
0176                 BOOST_LEAF_ASSERT(next_ == nullptr);
0177             }
0178         public:
0179             virtual void deactivate() const noexcept = 0;
0180         };
0181 
0182         template <class E>
0183         class capturing_slot_node:
0184             public capturing_node,
0185             public slot<E>
0186         {
0187             using impl = slot<E>;
0188 
0189             capturing_slot_node( capturing_slot_node const & ) = delete;
0190             capturing_slot_node & operator=( capturing_slot_node const & ) = delete;
0191 
0192             void deactivate() const noexcept final override
0193             {
0194                 impl::deactivate();
0195             }
0196 
0197             void unload( int err_id ) final override
0198             {
0199                 impl::unload(err_id);
0200             }
0201 
0202 #if BOOST_LEAF_CFG_DIAGNOSTICS
0203             void print( std::ostream & os, int err_id_to_print ) const final override
0204             {
0205                 impl::print(os, err_id_to_print);
0206             }
0207 #endif
0208 
0209         public:
0210 
0211             template <class T>
0212             BOOST_LEAF_CONSTEXPR capturing_slot_node( capture_list::node * * & last, int err_id, T && e ):
0213                 capturing_node(last)
0214             {
0215                 BOOST_LEAF_ASSERT(last == &next_);
0216                 BOOST_LEAF_ASSERT(next_ == nullptr);
0217                 impl::load(err_id, std::forward<T>(e));
0218             }
0219         };
0220 
0221 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0222         class capturing_exception_node:
0223             public capturing_node
0224         {
0225             capturing_exception_node( capturing_exception_node const & ) = delete;
0226             capturing_exception_node & operator=( capturing_exception_node const & ) = delete;
0227 
0228             void deactivate() const noexcept final override
0229             {
0230                 BOOST_LEAF_ASSERT(0);
0231             }
0232 
0233             void unload( int ) final override
0234             {
0235                 std::rethrow_exception(ex_);
0236             }
0237 
0238 #if BOOST_LEAF_CFG_DIAGNOSTICS
0239             void print( std::ostream &, int err_id_to_print ) const final override
0240             {
0241             }
0242 #endif
0243 
0244             std::exception_ptr const ex_;
0245 
0246         public:
0247 
0248             capturing_exception_node( capture_list::node * * & last, std::exception_ptr && ex ) noexcept:
0249                 capturing_node(last),
0250                 ex_(std::move(ex))
0251             {
0252                 BOOST_LEAF_ASSERT(last == &next_);
0253                 BOOST_LEAF_ASSERT(ex_);
0254             }
0255         };
0256 #endif
0257 
0258         node * * last_;
0259 
0260     public:
0261 
0262         dynamic_allocator() noexcept:
0263             capture_list(nullptr),
0264             last_(&first_)
0265         {
0266             BOOST_LEAF_ASSERT(first_ == nullptr);
0267         }
0268 
0269         dynamic_allocator( dynamic_allocator && other ) noexcept:
0270             capture_list(std::move(other)),
0271             last_(other.last_ == &other.first_? &first_ : other.last_)
0272         {
0273             BOOST_LEAF_ASSERT(last_ != nullptr);
0274             BOOST_LEAF_ASSERT(*last_ == nullptr);
0275             BOOST_LEAF_ASSERT(other.first_ == nullptr);
0276             other.last_ = &other.first_;
0277         }
0278 
0279         template <class E>
0280         typename std::decay<E>::type & dynamic_load(int err_id, E && e)
0281         {
0282             using T = typename std::decay<E>::type;
0283             BOOST_LEAF_ASSERT(last_ != nullptr);
0284             BOOST_LEAF_ASSERT(*last_ == nullptr);
0285             BOOST_LEAF_ASSERT(tls::read_ptr<slot<T>>() == nullptr);
0286             capturing_slot_node<T> * csn = new capturing_slot_node<T>(last_, err_id, std::forward<E>(e));
0287             csn->activate();
0288             return csn->value(err_id);
0289         }
0290 
0291         void deactivate() const noexcept
0292         {
0293             for_each(
0294                 []( capture_list::node const & n )
0295                 {
0296                     static_cast<capturing_node const &>(n).deactivate();
0297                 } );
0298         }
0299 
0300         template <class LeafResult>
0301         LeafResult extract_capture_list(int err_id) noexcept
0302         {
0303 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0304             if( std::exception_ptr ex = std::current_exception() )
0305                 (void) new capturing_exception_node(last_, std::move(ex));
0306 #endif
0307             leaf_detail::capture_list::node * const f = first_;
0308             first_ = nullptr;
0309             last_ = &first_;
0310             return { err_id, capture_list(f) };
0311         }
0312 
0313         using capture_list::unload;
0314         using capture_list::print;
0315     };
0316 
0317     template <>
0318     struct diagnostic<dynamic_allocator, false, false, false>
0319     {
0320         static constexpr bool is_invisible = true;
0321 
0322         template <class CharT, class Traits>
0323         BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, dynamic_allocator const & )
0324         {
0325         }
0326     };
0327 
0328     template <>
0329     inline void slot<dynamic_allocator>::deactivate() const noexcept
0330     {
0331         if( dynamic_allocator const * c = this->has_value() )
0332             c->deactivate();
0333         tls::write_ptr<slot<dynamic_allocator>>(prev_);
0334     }
0335 
0336     template <>
0337     inline void slot<dynamic_allocator>::unload( int err_id ) noexcept(false)
0338     {
0339         BOOST_LEAF_ASSERT(err_id);
0340         if( dynamic_allocator * da1 = this->has_value() )
0341             da1->unload(err_id);
0342     }
0343 
0344     template <class E>
0345     inline void dynamic_load_( int err_id, E && e )
0346     {
0347         if( slot<dynamic_allocator> * sl = tls::read_ptr<slot<dynamic_allocator>>() )
0348         {
0349             if( dynamic_allocator * c = sl->has_value() )
0350                 c->dynamic_load(err_id, std::forward<E>(e));
0351             else
0352                 sl->load(err_id).dynamic_load(err_id, std::forward<E>(e));
0353         }
0354     }
0355 
0356     template <class E, class F>
0357     inline void dynamic_accumulate_( int err_id, F && f )
0358     {
0359         if( slot<dynamic_allocator> * sl = tls::read_ptr<slot<dynamic_allocator>>() )
0360         {
0361             if( dynamic_allocator * c = sl->has_value(err_id) )
0362                 (void) std::forward<F>(f)(c->dynamic_load(err_id, E{}));
0363             else
0364                 (void) std::forward<F>(f)(sl->load(err_id).dynamic_load(err_id, E{}));
0365         }
0366     }
0367 
0368     template <bool OnError, class E>
0369     inline void dynamic_load( int err_id, E && e  ) noexcept(OnError)
0370     {
0371         if( OnError )
0372         {
0373 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0374             try
0375             {
0376 #endif
0377                 dynamic_load_(err_id, std::forward<E>(e));
0378 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0379             }
0380             catch(...)
0381             {
0382             }
0383 #endif
0384         }
0385         else
0386             dynamic_load_(err_id, std::forward<E>(e));
0387     }
0388 
0389     template <bool OnError, class E, class F>
0390     inline void dynamic_load_accumulate( int err_id, F && f  ) noexcept(OnError)
0391     {
0392         if( OnError )
0393         {
0394 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0395             try
0396             {
0397 #endif
0398                 dynamic_accumulate_<E>(err_id, std::forward<F>(f));
0399 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0400             }
0401             catch(...)
0402             {
0403             }
0404 #endif
0405         }
0406         else
0407             dynamic_accumulate_<E>(err_id, std::forward<F>(f));
0408     }
0409 }
0410 
0411 #endif
0412 
0413 ////////////////////////////////////////
0414 
0415 namespace leaf_detail
0416 {
0417     template <class E>
0418     inline void slot<E>::unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE)
0419     {
0420         BOOST_LEAF_ASSERT(err_id);
0421         if( this->key()!=err_id )
0422             return;
0423         if( impl * p = tls::read_ptr<slot<E>>() )
0424         {
0425             if( !p->has_value(err_id) )
0426                 *p = std::move(*this);
0427         }
0428 #if BOOST_LEAF_CFG_CAPTURE
0429         else
0430             dynamic_load<false>(err_id, std::move(*this).value(err_id));
0431 #endif
0432     }
0433 
0434     template <bool OnError, class E>
0435     BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept(OnError)
0436     {
0437         using T = typename std::decay<E>::type;
0438         static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
0439         static_assert(!std::is_same<T, error_id>::value, "Error objects of type error_id are not allowed");
0440         BOOST_LEAF_ASSERT((err_id&3)==1);
0441         if( slot<T> * p = tls::read_ptr<slot<T>>() )
0442         {
0443             if( !OnError || !p->has_value(err_id) )
0444                 (void) p->load(err_id, std::forward<E>(e));
0445         }
0446 #if BOOST_LEAF_CFG_CAPTURE
0447         else
0448             dynamic_load<OnError>(err_id, std::forward<E>(e));
0449 #endif        
0450         return 0;
0451     }
0452 
0453     template <bool OnError, class F>
0454     BOOST_LEAF_CONSTEXPR inline int load_slot_deferred( int err_id, F && f ) noexcept(OnError)
0455     {
0456         using E = typename function_traits<F>::return_type;
0457         using T = typename std::decay<E>::type;
0458         static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
0459         static_assert(!std::is_same<T, error_id>::value, "Error objects of type error_id are not allowed");
0460         BOOST_LEAF_ASSERT((err_id&3)==1);
0461         if( slot<T> * p = tls::read_ptr<slot<T>>() )
0462         {
0463             if( !OnError || !p->has_value(err_id) )
0464                 (void) p->load(err_id, std::forward<F>(f)());
0465         }
0466 #if BOOST_LEAF_CFG_CAPTURE
0467         else
0468             dynamic_load<OnError>(err_id, std::forward<F>(f)());
0469 #endif        
0470         return 0;
0471     }
0472 
0473     template <bool OnError, class F>
0474     BOOST_LEAF_CONSTEXPR inline int load_slot_accumulate( int err_id, F && f ) noexcept(OnError)
0475     {
0476         static_assert(function_traits<F>::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference");
0477         using E = typename std::decay<fn_arg_type<F,0>>::type;
0478         static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
0479         BOOST_LEAF_ASSERT((err_id&3)==1);
0480         if( auto sl = tls::read_ptr<slot<E>>() )
0481         {
0482             if( auto v = sl->has_value(err_id) )
0483                 (void) std::forward<F>(f)(*v);
0484             else
0485                 (void) std::forward<F>(f)(sl->load(err_id,E()));
0486         }
0487 #if BOOST_LEAF_CFG_CAPTURE
0488         else
0489             dynamic_load_accumulate<OnError, E>(err_id, std::forward<F>(f));
0490 #endif
0491         return 0;
0492     }
0493 }
0494 
0495 ////////////////////////////////////////
0496 
0497 namespace leaf_detail
0498 {
0499     template <class T, int Arity = function_traits<T>::arity>
0500     struct load_item
0501     {
0502         static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument");
0503     };
0504 
0505     template <class E>
0506     struct load_item<E, -1>
0507     {
0508         BOOST_LEAF_CONSTEXPR static int load_( int err_id, E && e ) noexcept
0509         {
0510             return load_slot<false>(err_id, std::forward<E>(e));
0511         }
0512     };
0513 
0514     template <class F>
0515     struct load_item<F, 0>
0516     {
0517         BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept
0518         {
0519             return load_slot_deferred<false>(err_id, std::forward<F>(f));
0520         }
0521     };
0522 
0523     template <class F>
0524     struct load_item<F, 1>
0525     {
0526         BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept
0527         {
0528             return load_slot_accumulate<false>(err_id, std::forward<F>(f));
0529         }
0530     };
0531 }
0532 
0533 ////////////////////////////////////////
0534 
0535 namespace leaf_detail
0536 {
0537     struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id;
0538 
0539     template <class=void>
0540     struct BOOST_LEAF_SYMBOL_VISIBLE id_factory
0541     {
0542         static atomic_unsigned_int counter;
0543 
0544         BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept
0545         {
0546             auto id = (counter+=4);
0547             BOOST_LEAF_ASSERT((id&3)==1);
0548             return id;
0549         }
0550     };
0551 
0552     template <class T>
0553     atomic_unsigned_int id_factory<T>::counter(unsigned(-3));
0554 
0555     inline int current_id() noexcept
0556     {
0557         unsigned id = tls::read_uint<tls_tag_id_factory_current_id>();
0558         BOOST_LEAF_ASSERT(id==0 || (id&3)==1);
0559         return int(id);
0560     }
0561 
0562     inline int new_id() noexcept
0563     {
0564         unsigned id = id_factory<>::generate_next_id();
0565         tls::write_uint<tls_tag_id_factory_current_id>(id);
0566         return int(id);
0567     }
0568 
0569     struct inject_loc
0570     {
0571         char const * const file;
0572         int const line;
0573         char const * const fn;
0574 
0575         template <class T>
0576         friend T operator+( inject_loc loc, T && x ) noexcept
0577         {
0578             x.load_source_location_(loc.file, loc.line, loc.fn);
0579             return std::move(x);
0580         }
0581     };
0582 }
0583 
0584 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0585 
0586 namespace leaf_detail
0587 {
0588     class leaf_category final: public std::error_category
0589     {
0590         bool equivalent( int,  std::error_condition const & ) const noexcept final override { return false; }
0591         bool equivalent( std::error_code const &, int ) const noexcept final override { return false; }
0592         char const * name() const noexcept final override { return "LEAF error"; }
0593         std::string message( int ) const final override { return name(); }
0594     public:
0595         ~leaf_category() noexcept final override { }
0596     };
0597 
0598     template <class=void>
0599     struct get_error_category
0600     {
0601         static leaf_category cat;
0602     };
0603 
0604     template <class T>
0605     leaf_category get_error_category<T>::cat;
0606 
0607     inline int import_error_code( std::error_code const & ec ) noexcept
0608     {
0609         if( int err_id = ec.value() )
0610         {
0611             std::error_category const & cat = get_error_category<>::cat;
0612             if( &ec.category() == &cat )
0613             {
0614                 BOOST_LEAF_ASSERT((err_id&3)==1);
0615                 return (err_id&~3)|1;
0616             }
0617             else
0618             {
0619                 err_id = new_id();
0620                 (void) load_slot<false>(err_id, ec);
0621                 return (err_id&~3)|1;
0622             }
0623         }
0624         else
0625             return 0;
0626     }
0627 }
0628 
0629 inline bool is_error_id( std::error_code const & ec ) noexcept
0630 {
0631     bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat);
0632     BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1));
0633     return res;
0634 }
0635 
0636 #endif
0637 
0638 ////////////////////////////////////////
0639 
0640 namespace leaf_detail
0641 {
0642     BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept;
0643 }
0644 
0645 class BOOST_LEAF_SYMBOL_VISIBLE error_id
0646 {
0647     friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept;
0648 
0649     int value_;
0650 
0651     BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept:
0652         value_(value)
0653     {
0654         BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1));
0655     }
0656 
0657 public:
0658 
0659     BOOST_LEAF_CONSTEXPR error_id() noexcept:
0660         value_(0)
0661     {
0662     }
0663 
0664 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0665     error_id( std::error_code const & ec ) noexcept:
0666         value_(leaf_detail::import_error_code(ec))
0667     {
0668         BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1));
0669     }
0670 
0671     template <class Enum>
0672     error_id( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
0673         value_(leaf_detail::import_error_code(e))
0674     {
0675     }
0676 
0677     operator std::error_code() const noexcept
0678     {
0679         return std::error_code(value_, leaf_detail::get_error_category<>::cat);
0680     }
0681 #endif
0682 
0683     BOOST_LEAF_CONSTEXPR error_id load() const noexcept
0684     {
0685         return *this;
0686     }
0687 
0688     template <class Item>
0689     BOOST_LEAF_CONSTEXPR error_id load(Item && item) const noexcept
0690     {
0691         if (int err_id = value())
0692         {
0693             int const unused[] = { 42, leaf_detail::load_item<Item>::load_(err_id, std::forward<Item>(item)) };
0694             (void)unused;
0695         }
0696         return *this;
0697     }
0698 
0699     template <class... Item>
0700     BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept
0701     {
0702         if( int err_id = value() )
0703         {
0704             int const unused[] = { 42, leaf_detail::load_item<Item>::load_(err_id, std::forward<Item>(item))... };
0705             (void) unused;
0706         }
0707         return *this;
0708     }
0709 
0710     BOOST_LEAF_CONSTEXPR int value() const noexcept
0711     {
0712         BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1));
0713         return value_;
0714     }
0715 
0716     BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept
0717     {
0718         return value_ != 0;
0719     }
0720 
0721     BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept
0722     {
0723         return a.value_ == b.value_;
0724     }
0725 
0726     BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept
0727     {
0728         return !(a == b);
0729     }
0730 
0731     BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept
0732     {
0733         return a.value_ < b.value_;
0734     }
0735 
0736     template <class CharT, class Traits>
0737     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, error_id x )
0738     {
0739         return os << x.value_;
0740     }
0741 
0742     BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept
0743     {
0744         BOOST_LEAF_ASSERT(file&&*file);
0745         BOOST_LEAF_ASSERT(line>0);
0746         BOOST_LEAF_ASSERT(function&&*function);
0747         BOOST_LEAF_ASSERT(value_);
0748         (void) load(e_source_location {file,line,function});
0749     }
0750 };
0751 
0752 namespace leaf_detail
0753 {
0754     BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept
0755     {
0756         BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1);
0757         return error_id((err_id&~3)|1);
0758     }
0759 }
0760 
0761 inline error_id new_error() noexcept
0762 {
0763     return leaf_detail::make_error_id(leaf_detail::new_id());
0764 }
0765 
0766 template <class... Item>
0767 inline error_id new_error( Item && ... item ) noexcept
0768 {
0769     return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward<Item>(item)...);
0770 }
0771 
0772 inline error_id current_error() noexcept
0773 {
0774     return leaf_detail::make_error_id(leaf_detail::current_id());
0775 }
0776 
0777 ////////////////////////////////////////////
0778 
0779 class polymorphic_context
0780 {
0781 };
0782 
0783 #if BOOST_LEAF_CFG_CAPTURE
0784 using context_ptr = std::shared_ptr<polymorphic_context>;
0785 #endif
0786 
0787 ////////////////////////////////////////////
0788 
0789 template <class Ctx>
0790 class context_activator
0791 {
0792     context_activator( context_activator const & ) = delete;
0793     context_activator & operator=( context_activator const & ) = delete;
0794 
0795     Ctx * ctx_;
0796 
0797 public:
0798 
0799     explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept:
0800         ctx_(ctx.is_active() ? nullptr : &ctx)
0801     {
0802         if( ctx_ )
0803             ctx_->activate();
0804     }
0805 
0806     BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept:
0807         ctx_(x.ctx_)
0808     {
0809         x.ctx_ = nullptr;
0810     }
0811 
0812     BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept
0813     {
0814         if( ctx_ && ctx_->is_active() )
0815             ctx_->deactivate();
0816     }
0817 };
0818 
0819 ////////////////////////////////////////////
0820 
0821 template <class R>
0822 struct is_result_type: std::false_type
0823 {
0824 };
0825 
0826 template <class R>
0827 struct is_result_type<R const>: is_result_type<R>
0828 {
0829 };
0830 
0831 } }
0832 
0833 #endif