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