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
0005
0006
0007
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