Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:37:41

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