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
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/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