Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:12

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