File indexing completed on 2025-07-11 08:18:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #ifndef BOOST_OUTCOME_VALUE_STORAGE_HPP
0032 #define BOOST_OUTCOME_VALUE_STORAGE_HPP
0033
0034 #include "../config.hpp"
0035
0036 BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
0037
0038 namespace detail
0039 {
0040
0041 template <class T, bool isCopyOrMoveConstructible = std::is_copy_constructible<T>::value || std::is_move_constructible<T>::value,
0042 bool isDefaultConstructibleAndCopyOrMoveAssignable =
0043 std::is_default_constructible<T>::value && (std::is_copy_assignable<T>::value || std::is_move_assignable<T>::value)>
0044 struct move_assign_to_empty;
0045
0046 template <class T> struct move_assign_to_empty<T, true, false>
0047 {
0048 move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
0049 };
0050 template <class T> struct move_assign_to_empty<T, true, true>
0051 {
0052 move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
0053 };
0054
0055 template <class T> struct move_assign_to_empty<T, false, true>
0056 {
0057 move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_default_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
0058 {
0059 new(dest) T;
0060 *dest = static_cast<T &&>(*o);
0061 }
0062 };
0063
0064 template <> struct move_assign_to_empty<void, false, false>
0065 {
0066 move_assign_to_empty(void *, void *) noexcept { }
0067 };
0068 template <> struct move_assign_to_empty<const void, false, false>
0069 {
0070 move_assign_to_empty(const void *, const void *) noexcept { }
0071 };
0072
0073 template <class T, bool isCopyConstructible = std::is_copy_constructible<T>::value,
0074 bool isDefaultConstructibleAndCopyAssignable = std::is_default_constructible<T>::value && std::is_copy_assignable<T>::value>
0075 struct copy_assign_to_empty;
0076
0077 template <class T> struct copy_assign_to_empty<T, true, false>
0078 {
0079 copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
0080 };
0081 template <class T> struct copy_assign_to_empty<T, true, true>
0082 {
0083 copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
0084 };
0085
0086 template <class T> struct copy_assign_to_empty<T, false, true>
0087 {
0088 copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_default_constructible<T>::value && std::is_nothrow_copy_assignable<T>::value)
0089 {
0090 new(dest) T;
0091 *dest = *o;
0092 }
0093 };
0094
0095 template <> struct copy_assign_to_empty<void, false, false>
0096 {
0097 copy_assign_to_empty(void *, void *) noexcept { }
0098 };
0099 template <> struct copy_assign_to_empty<const void, false, false>
0100 {
0101 copy_assign_to_empty(const void *, const void *) noexcept { }
0102 };
0103
0104 template <class T, bool nothrow> struct strong_swap_impl
0105 {
0106 constexpr strong_swap_impl(bool &allgood, T &a, T &b)
0107 {
0108 allgood = true;
0109 using std::swap;
0110 swap(a, b);
0111 }
0112 };
0113 template <class T, bool nothrow> struct strong_placement_impl
0114 {
0115 template <class F> constexpr strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
0116 {
0117 allgood = true;
0118 new(a) T(static_cast<T &&>(*b));
0119 b->~T();
0120 f();
0121 }
0122 };
0123 #ifndef BOOST_NO_EXCEPTIONS
0124 template <class T> struct strong_swap_impl<T, false>
0125 {
0126 strong_swap_impl(bool &allgood, T &a, T &b)
0127 {
0128 allgood = true;
0129 T v(static_cast<T &&>(a));
0130 try
0131 {
0132 a = static_cast<T &&>(b);
0133 }
0134 catch(...)
0135 {
0136
0137 try
0138 {
0139 a = static_cast<T &&>(v);
0140
0141 }
0142 catch(...)
0143 {
0144
0145 allgood = false;
0146
0147 }
0148 throw;
0149 }
0150
0151 try
0152 {
0153 b = static_cast<T &&>(v);
0154 }
0155 catch(...)
0156 {
0157
0158 try
0159 {
0160 b = static_cast<T &&>(a);
0161 a = static_cast<T &&>(v);
0162
0163 }
0164 catch(...)
0165 {
0166
0167 allgood = false;
0168
0169 }
0170 throw;
0171 }
0172 }
0173 };
0174 template <class T> struct strong_placement_impl<T, false>
0175 {
0176 template <class F> strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
0177 {
0178 new(a) T(static_cast<T &&>(*b));
0179 try
0180 {
0181 b->~T();
0182 f();
0183 }
0184 catch(...)
0185 {
0186
0187 if(allgood)
0188 {
0189 try
0190 {
0191 new(b) T(static_cast<T &&>(*a));
0192
0193 }
0194 catch(...)
0195 {
0196
0197 allgood = false;
0198
0199 }
0200 throw;
0201 }
0202 }
0203 }
0204 };
0205 #endif
0206 }
0207
0208
0209
0210 BOOST_OUTCOME_TEMPLATE(class T)
0211 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
0212 constexpr inline void strong_swap(bool &allgood, T &a, T &b) noexcept(detail::is_nothrow_swappable<T>::value)
0213 {
0214 detail::strong_swap_impl<T, detail::is_nothrow_swappable<T>::value>(allgood, a, b);
0215 }
0216
0217
0218 BOOST_OUTCOME_TEMPLATE(class T, class F)
0219 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
0220 constexpr inline void strong_placement(bool &allgood, T *a, T *b, F &&f) noexcept(std::is_nothrow_move_constructible<T>::value)
0221 {
0222 detail::strong_placement_impl<T, std::is_nothrow_move_constructible<T>::value>(allgood, a, b, static_cast<F &&>(f));
0223 }
0224
0225 namespace detail
0226 {
0227 template <class T>
0228 constexpr
0229 #ifdef _MSC_VER
0230 __declspec(noreturn)
0231 #elif defined(__GNUC__) || defined(__clang__)
0232 __attribute__((noreturn))
0233 #endif
0234 void
0235 make_ub(T && )
0236 {
0237 BOOST_OUTCOME_ASSERT(false);
0238 #if defined(__GNUC__) || defined(__clang__)
0239 __builtin_unreachable();
0240 #elif defined(_MSC_VER)
0241 __assume(0);
0242 #endif
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 #define BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS 0
0258 enum class status : uint16_t
0259 {
0260
0261 none = 0,
0262
0263 have_value = (1U << 0U),
0264 have_error = (1U << 1U),
0265 have_exception = (2U << 1U),
0266 have_error_exception = (3U << 1U),
0267
0268
0269 have_lost_consistency = (1U << 3U),
0270 have_value_lost_consistency = (1U << 0U) | (1U << 3U),
0271 have_error_lost_consistency = (1U << 1U) | (1U << 3U),
0272 have_exception_lost_consistency = (2U << 1U) | (1U << 3U),
0273 have_error_exception_lost_consistency = (3U << 1U) | (1U << 3U),
0274
0275
0276 have_error_is_errno = (1U << 4U),
0277 have_error_error_is_errno = (1U << 1U) | (1U << 4U),
0278 have_error_exception_error_is_errno = (3U << 1U) | (1U << 4U),
0279
0280 have_error_lost_consistency_error_is_errno = (1U << 1U) | (1U << 3U) | (1U << 4U),
0281 have_error_exception_lost_consistency_error_is_errno = (3U << 1U) | (1U << 3U) | (1U << 4U),
0282
0283
0284 have_moved_from = (1U << 5U)
0285 };
0286 struct status_bitfield_type
0287 {
0288 status status_value{status::none};
0289 uint16_t spare_storage_value{0};
0290
0291 constexpr status_bitfield_type() = default;
0292 constexpr status_bitfield_type(status v) noexcept
0293 : status_value(v)
0294 {
0295 }
0296 constexpr status_bitfield_type(status v, uint16_t s) noexcept
0297 : status_value(v)
0298 , spare_storage_value(s)
0299 {
0300 }
0301 constexpr status_bitfield_type(const status_bitfield_type &) = default;
0302 constexpr status_bitfield_type(status_bitfield_type &&) = default;
0303 constexpr status_bitfield_type &operator=(const status_bitfield_type &) = default;
0304 constexpr status_bitfield_type &operator=(status_bitfield_type &&) = default;
0305
0306
0307 constexpr bool have_value() const noexcept
0308 {
0309 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0310 return (status_value == status::have_value)
0311 || (status_value == status::have_value_lost_consistency)
0312 ;
0313 #else
0314 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_value)) != 0;
0315 #endif
0316 }
0317 constexpr bool have_error() const noexcept
0318 {
0319 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0320 return (status_value == status::have_error)
0321 || (status_value == status::have_error_exception)
0322 || (status_value == status::have_error_lost_consistency)
0323 || (status_value == status::have_error_exception_lost_consistency)
0324 || (status_value == status::have_error_error_is_errno)
0325 || (status_value == status::have_error_exception_error_is_errno)
0326 || (status_value == status::have_error_lost_consistency_error_is_errno)
0327 || (status_value == status::have_error_exception_lost_consistency_error_is_errno)
0328 ;
0329 #else
0330 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error)) != 0;
0331 #endif
0332 }
0333 constexpr bool have_exception() const noexcept
0334 {
0335 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0336 return (status_value == status::have_exception)
0337 || (status_value == status::have_error_exception)
0338 || (status_value == status::have_exception_lost_consistency)
0339 || (status_value == status::have_error_exception_lost_consistency)
0340 || (status_value == status::have_error_exception_error_is_errno)
0341 || (status_value == status::have_error_exception_lost_consistency_error_is_errno)
0342 ;
0343 #else
0344 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_exception)) != 0;
0345 #endif
0346 }
0347 constexpr bool have_lost_consistency() const noexcept
0348 {
0349 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0350 return (status_value == status::have_value_lost_consistency)
0351 || (status_value == status::have_error_lost_consistency)
0352 || (status_value == status::have_exception_lost_consistency)
0353 || (status_value == status::have_error_lost_consistency_error_is_errno)
0354 || (status_value == status::have_error_exception_lost_consistency_error_is_errno)
0355 ;
0356 #else
0357 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_lost_consistency)) != 0;
0358 #endif
0359 }
0360 constexpr bool have_error_is_errno() const noexcept
0361 {
0362 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0363 return (status_value == status::have_error_error_is_errno)
0364 || (status_value == status::have_error_exception_error_is_errno)
0365 || (status_value == status::have_error_lost_consistency_error_is_errno)
0366 || (status_value == status::have_error_exception_lost_consistency_error_is_errno)
0367 ;
0368 #else
0369 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error_is_errno)) != 0;
0370 #endif
0371 }
0372 constexpr bool have_moved_from() const noexcept
0373 {
0374 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0375 #error Fixme
0376 #else
0377 return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_moved_from)) != 0;
0378 #endif
0379 }
0380
0381 constexpr status_bitfield_type &set_have_value(bool v) noexcept
0382 {
0383 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0384 switch(status_value)
0385 {
0386 case status::none:
0387 if(v)
0388 {
0389 status_value = status::have_value;
0390 }
0391 break;
0392 case status::have_value:
0393 if(!v)
0394 {
0395 status_value = status::none;
0396 }
0397 break;
0398 case status::have_error:
0399 if(v)
0400 {
0401 make_ub(*this);
0402 }
0403 break;
0404 case status::have_exception:
0405 if(v)
0406 {
0407 make_ub(*this);
0408 }
0409 break;
0410 case status::have_error_exception:
0411 if(v)
0412 {
0413 make_ub(*this);
0414 }
0415 break;
0416 case status::have_value_lost_consistency:
0417 if(!v)
0418 {
0419 status_value = status::none;
0420 }
0421 break;
0422 case status::have_error_lost_consistency:
0423 if(v)
0424 {
0425 make_ub(*this);
0426 }
0427 break;
0428 case status::have_exception_lost_consistency:
0429 if(v)
0430 {
0431 make_ub(*this);
0432 }
0433 break;
0434 case status::have_error_exception_lost_consistency:
0435 if(v)
0436 {
0437 make_ub(*this);
0438 }
0439 break;
0440 case status::have_error_error_is_errno:
0441 if(v)
0442 {
0443 make_ub(*this);
0444 }
0445 break;
0446 case status::have_error_exception_error_is_errno:
0447 if(v)
0448 {
0449 make_ub(*this);
0450 }
0451 break;
0452 case status::have_error_lost_consistency_error_is_errno:
0453 if(v)
0454 {
0455 make_ub(*this);
0456 }
0457 break;
0458 case status::have_error_exception_lost_consistency_error_is_errno:
0459 if(v)
0460 {
0461 make_ub(*this);
0462 }
0463 break;
0464 }
0465 #else
0466 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_value)) :
0467 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_value)));
0468 #endif
0469 return *this;
0470 }
0471 constexpr status_bitfield_type &set_have_error(bool v) noexcept
0472 {
0473 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0474 switch(status_value)
0475 {
0476 case status::none:
0477 if(v)
0478 {
0479 status_value = status::have_error;
0480 }
0481 break;
0482 case status::have_value:
0483 if(v)
0484 {
0485 make_ub(*this);
0486 }
0487 break;
0488 case status::have_error:
0489 if(!v)
0490 {
0491 status_value = status::none;
0492 }
0493 break;
0494 case status::have_exception:
0495 if(v)
0496 {
0497 status_value = status::have_error_exception;
0498 }
0499 break;
0500 case status::have_error_exception:
0501 if(!v)
0502 {
0503 status_value = status::have_exception;
0504 }
0505 break;
0506 case status::have_value_lost_consistency:
0507 if(v)
0508 {
0509 make_ub(*this);
0510 }
0511 break;
0512 case status::have_error_lost_consistency:
0513 if(!v)
0514 {
0515 status_value = status::none;
0516 }
0517 break;
0518 case status::have_exception_lost_consistency:
0519 if(v)
0520 {
0521 status_value = status::have_error_exception_lost_consistency;
0522 }
0523 break;
0524 case status::have_error_exception_lost_consistency:
0525 if(!v)
0526 {
0527 status_value = status::have_exception_lost_consistency;
0528 }
0529 break;
0530 case status::have_error_error_is_errno:
0531 if(!v)
0532 {
0533 status_value = status::none;
0534 }
0535 break;
0536 case status::have_error_exception_error_is_errno:
0537 if(!v)
0538 {
0539 status_value = status::have_exception;
0540 }
0541 break;
0542 case status::have_error_lost_consistency_error_is_errno:
0543 if(!v)
0544 {
0545 status_value = status::none;
0546 }
0547 break;
0548 case status::have_error_exception_lost_consistency_error_is_errno:
0549 if(!v)
0550 {
0551 status_value = status::have_exception_lost_consistency;
0552 }
0553 break;
0554 }
0555 #else
0556 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error)) :
0557 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error)));
0558 #endif
0559 return *this;
0560 }
0561 constexpr status_bitfield_type &set_have_exception(bool v) noexcept
0562 {
0563 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0564 switch(status_value)
0565 {
0566 case status::none:
0567 if(v)
0568 {
0569 status_value = status::have_exception;
0570 }
0571 break;
0572 case status::have_value:
0573 if(v)
0574 {
0575 make_ub(*this);
0576 }
0577 break;
0578 case status::have_error:
0579 if(v)
0580 {
0581 status_value = status::have_error_exception;
0582 }
0583 break;
0584 case status::have_exception:
0585 if(!v)
0586 {
0587 status_value = status::none;
0588 }
0589 break;
0590 case status::have_error_exception:
0591 if(!v)
0592 {
0593 status_value = status::have_error;
0594 }
0595 break;
0596 case status::have_value_lost_consistency:
0597 if(v)
0598 {
0599 make_ub(*this);
0600 }
0601 break;
0602 case status::have_error_lost_consistency:
0603 if(v)
0604 {
0605 status_value = status::have_error_exception_lost_consistency;
0606 }
0607 break;
0608 case status::have_exception_lost_consistency:
0609 if(!v)
0610 {
0611 status_value = status::none;
0612 }
0613 break;
0614 case status::have_error_exception_lost_consistency:
0615 if(!v)
0616 {
0617 status_value = status::have_error_lost_consistency;
0618 }
0619 break;
0620 case status::have_error_error_is_errno:
0621 if(v)
0622 {
0623 status_value = status::have_error_exception_error_is_errno;
0624 }
0625 break;
0626 case status::have_error_exception_error_is_errno:
0627 if(!v)
0628 {
0629 status_value = status::have_error_error_is_errno;
0630 }
0631 break;
0632 case status::have_error_lost_consistency_error_is_errno:
0633 if(v)
0634 {
0635 status_value = status::have_error_exception_lost_consistency_error_is_errno;
0636 }
0637 break;
0638 case status::have_error_exception_lost_consistency_error_is_errno:
0639 if(!v)
0640 {
0641 status_value = status::have_error_lost_consistency_error_is_errno;
0642 }
0643 break;
0644 }
0645 #else
0646 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_exception)) :
0647 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_exception)));
0648 #endif
0649 return *this;
0650 }
0651 constexpr status_bitfield_type &set_have_error_is_errno(bool v) noexcept
0652 {
0653 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0654 switch(status_value)
0655 {
0656 case status::none:
0657 make_ub(*this);
0658 break;
0659 case status::have_value:
0660 make_ub(*this);
0661 break;
0662 case status::have_error:
0663 if(v)
0664 {
0665 status_value = status::have_error_error_is_errno;
0666 }
0667 break;
0668 case status::have_exception:
0669 make_ub(*this);
0670 break;
0671 case status::have_error_exception:
0672 if(v)
0673 {
0674 status_value = status::have_error_exception_error_is_errno;
0675 }
0676 break;
0677 case status::have_value_lost_consistency:
0678 make_ub(*this);
0679 break;
0680 case status::have_error_lost_consistency:
0681 if(v)
0682 {
0683 status_value = status::have_error_lost_consistency_error_is_errno;
0684 }
0685 break;
0686 case status::have_exception_lost_consistency:
0687 make_ub(*this);
0688 break;
0689 case status::have_error_exception_lost_consistency:
0690 if(v)
0691 {
0692 status_value = status::have_error_exception_lost_consistency_error_is_errno;
0693 }
0694 break;
0695 case status::have_error_error_is_errno:
0696 if(!v)
0697 {
0698 status_value = status::have_error;
0699 }
0700 break;
0701 case status::have_error_exception_error_is_errno:
0702 if(!v)
0703 {
0704 status_value = status::have_error_exception;
0705 }
0706 break;
0707 case status::have_error_lost_consistency_error_is_errno:
0708 if(!v)
0709 {
0710 status_value = status::have_error_lost_consistency;
0711 }
0712 break;
0713 case status::have_error_exception_lost_consistency_error_is_errno:
0714 if(!v)
0715 {
0716 status_value = status::have_error_exception_lost_consistency;
0717 }
0718 break;
0719 }
0720 #else
0721 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error_is_errno)) :
0722 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error_is_errno)));
0723 #endif
0724 return *this;
0725 }
0726 constexpr status_bitfield_type &set_have_lost_consistency(bool v) noexcept
0727 {
0728 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0729 switch(status_value)
0730 {
0731 case status::none:
0732 if(v)
0733 {
0734 make_ub(*this);
0735 }
0736 break;
0737 case status::have_value:
0738 if(v)
0739 {
0740 status_value = status::have_value_lost_consistency;
0741 }
0742 break;
0743 case status::have_error:
0744 if(v)
0745 {
0746 status_value = status::have_error_lost_consistency;
0747 }
0748 break;
0749 case status::have_exception:
0750 if(v)
0751 {
0752 status_value = status::have_exception_lost_consistency;
0753 }
0754 break;
0755 case status::have_error_exception:
0756 if(v)
0757 {
0758 status_value = status::have_error_exception_lost_consistency;
0759 }
0760 break;
0761 case status::have_value_lost_consistency:
0762 if(!v)
0763 {
0764 status_value = status::have_value;
0765 }
0766 break;
0767 case status::have_error_lost_consistency:
0768 if(!v)
0769 {
0770 status_value = status::have_error;
0771 }
0772 break;
0773 case status::have_exception_lost_consistency:
0774 if(!v)
0775 {
0776 status_value = status::have_exception;
0777 }
0778 break;
0779 case status::have_error_exception_lost_consistency:
0780 if(!v)
0781 {
0782 status_value = status::have_error_exception;
0783 }
0784 break;
0785 case status::have_error_error_is_errno:
0786 if(v)
0787 {
0788 status_value = status::have_error_lost_consistency_error_is_errno;
0789 }
0790 break;
0791 case status::have_error_exception_error_is_errno:
0792 if(v)
0793 {
0794 status_value = status::have_error_exception_lost_consistency_error_is_errno;
0795 }
0796 break;
0797 case status::have_error_lost_consistency_error_is_errno:
0798 if(!v)
0799 {
0800 status_value = status::have_error_exception_error_is_errno;
0801 }
0802 break;
0803 case status::have_error_exception_lost_consistency_error_is_errno:
0804 if(!v)
0805 {
0806 status_value = status::have_error_exception_error_is_errno;
0807 }
0808 break;
0809 }
0810 #else
0811 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_lost_consistency)) :
0812 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_lost_consistency)));
0813 #endif
0814 return *this;
0815 }
0816 constexpr status_bitfield_type &set_have_moved_from(bool v) noexcept
0817 {
0818 #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
0819 #error Fixme
0820 #else
0821 status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_moved_from)) :
0822 (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_moved_from)));
0823 #endif
0824 return *this;
0825 }
0826 };
0827 #if !defined(NDEBUG)
0828
0829 static_assert(sizeof(status_bitfield_type) == 4, "status_bitfield_type is not sized 4 bytes!");
0830 static_assert(std::is_trivially_copyable<status_bitfield_type>::value, "status_bitfield_type is not trivially copyable!");
0831 static_assert(std::is_trivially_assignable<status_bitfield_type, status_bitfield_type>::value, "status_bitfield_type is not trivially assignable!");
0832 static_assert(std::is_trivially_destructible<status_bitfield_type>::value, "status_bitfield_type is not trivially destructible!");
0833 static_assert(std::is_trivially_copy_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially copy constructible!");
0834 static_assert(std::is_trivially_move_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially move constructible!");
0835 static_assert(std::is_trivially_copy_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially copy assignable!");
0836 static_assert(std::is_trivially_move_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially move assignable!");
0837
0838 static_assert(std::is_standard_layout<status_bitfield_type>::value, "status_bitfield_type is not a standard layout type!");
0839 #endif
0840
0841 template <class State> constexpr inline void _set_error_is_errno(State & ) {}
0842
0843 #ifdef _MSC_VER
0844 #pragma warning(push)
0845 #pragma warning(disable : 4127)
0846 #pragma warning(disable : 4624)
0847 #endif
0848
0849 template <class T, class E> struct value_storage_trivial
0850 {
0851 using value_type = T;
0852 using error_type = E;
0853
0854
0855 struct disable_in_place_value_type
0856 {
0857 };
0858 struct disable_in_place_error_type
0859 {
0860 };
0861 using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
0862 using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
0863 using _value_type_ = devoid<value_type>;
0864 using _error_type_ = devoid<error_type>;
0865
0866 union
0867 {
0868 empty_type _empty;
0869 _value_type_ _value;
0870 _error_type_ _error;
0871 };
0872 status_bitfield_type _status;
0873 constexpr value_storage_trivial() noexcept
0874 : _empty{}
0875 {
0876 }
0877 value_storage_trivial(const value_storage_trivial &) = default;
0878 value_storage_trivial(value_storage_trivial &&) = default;
0879 value_storage_trivial &operator=(const value_storage_trivial &) = default;
0880 value_storage_trivial &operator=(value_storage_trivial &&) = default;
0881 ~value_storage_trivial() = default;
0882 constexpr explicit value_storage_trivial(status_bitfield_type status)
0883 : _empty()
0884 , _status(status)
0885 {
0886 }
0887 template <class... Args>
0888 constexpr explicit value_storage_trivial(in_place_type_t<_value_type> ,
0889 Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
0890 : _value(static_cast<Args &&>(args)...)
0891 , _status(status::have_value)
0892 {
0893 }
0894 template <class U, class... Args>
0895 constexpr value_storage_trivial(in_place_type_t<_value_type> , std::initializer_list<U> il,
0896 Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
0897 : _value(il, static_cast<Args &&>(args)...)
0898 , _status(status::have_value)
0899 {
0900 }
0901 template <class... Args>
0902 constexpr explicit value_storage_trivial(in_place_type_t<_error_type> ,
0903 Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
0904 : _error(static_cast<Args &&>(args)...)
0905 , _status(status::have_error)
0906 {
0907 _set_error_is_errno(*this);
0908 }
0909 template <class U, class... Args>
0910 constexpr value_storage_trivial(in_place_type_t<_error_type> , std::initializer_list<U> il,
0911 Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
0912 : _error(il, static_cast<Args &&>(args)...)
0913 , _status(status::have_error)
0914 {
0915 _set_error_is_errno(*this);
0916 }
0917
0918 struct nonvoid_converting_constructor_tag
0919 {
0920 };
0921 template <class U, class V>
0922 static constexpr bool enable_nonvoid_converting_constructor =
0923 !(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value)
0924 && detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
0925 BOOST_OUTCOME_TEMPLATE(class U, class V)
0926 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
0927 constexpr explicit value_storage_trivial(const value_storage_trivial<U, V> &o,
0928 nonvoid_converting_constructor_tag = {}) noexcept(detail::is_nothrow_constructible<_value_type_, U> &&
0929 detail::is_nothrow_constructible<_error_type_, V>)
0930 : value_storage_trivial(o._status.have_value() ?
0931 value_storage_trivial(in_place_type<value_type>, o._value) :
0932 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial()))
0933 {
0934 _status = o._status;
0935 }
0936 BOOST_OUTCOME_TEMPLATE(class U, class V)
0937 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
0938 constexpr explicit value_storage_trivial(value_storage_trivial<U, V> &&o,
0939 nonvoid_converting_constructor_tag = {}) noexcept(detail::is_nothrow_constructible<_value_type_, U> &&
0940 detail::is_nothrow_constructible<_error_type_, V>)
0941 : value_storage_trivial(
0942 o._status.have_value() ?
0943 value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
0944 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial()))
0945 {
0946 _status = o._status;
0947 }
0948
0949 struct void_value_converting_constructor_tag
0950 {
0951 };
0952 template <class V>
0953 static constexpr bool enable_void_value_converting_constructor =
0954 std::is_default_constructible<value_type>::value && detail::is_constructible<error_type, V>;
0955 BOOST_OUTCOME_TEMPLATE(class V)
0956 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
0957 constexpr explicit value_storage_trivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag = {}) noexcept(
0958 std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
0959 : value_storage_trivial(o._status.have_value() ?
0960 value_storage_trivial(in_place_type<value_type>) :
0961 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial()))
0962 {
0963 _status = o._status;
0964 }
0965 BOOST_OUTCOME_TEMPLATE(class V)
0966 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
0967 constexpr explicit value_storage_trivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag = {}) noexcept(
0968 std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
0969 : value_storage_trivial(
0970 o._status.have_value() ?
0971 value_storage_trivial(in_place_type<value_type>) :
0972 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial()))
0973 {
0974 _status = o._status;
0975 }
0976
0977 struct void_error_converting_constructor_tag
0978 {
0979 };
0980 template <class U>
0981 static constexpr bool enable_void_error_converting_constructor =
0982 std::is_default_constructible<error_type>::value && detail::is_constructible<value_type, U>;
0983 BOOST_OUTCOME_TEMPLATE(class U)
0984 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
0985 constexpr explicit value_storage_trivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag = {}) noexcept(
0986 detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
0987 : value_storage_trivial(o._status.have_value() ?
0988 value_storage_trivial(in_place_type<value_type>, o._value) :
0989 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial()))
0990 {
0991 _status = o._status;
0992 }
0993 BOOST_OUTCOME_TEMPLATE(class U)
0994 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
0995 constexpr explicit value_storage_trivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag = {}) noexcept(
0996 detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
0997 : value_storage_trivial(o._status.have_value() ?
0998 value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
0999 (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial()))
1000 {
1001 _status = o._status;
1002 }
1003 constexpr void swap(value_storage_trivial &o) noexcept
1004 {
1005
1006 auto temp = static_cast<value_storage_trivial &&>(*this);
1007 *this = static_cast<value_storage_trivial &&>(o);
1008 o = static_cast<value_storage_trivial &&>(temp);
1009 }
1010 };
1011
1012
1013
1014
1015 template <class T, class E> struct value_storage_nontrivial
1016 {
1017 using value_type = T;
1018 using error_type = E;
1019 struct disable_in_place_value_type
1020 {
1021 };
1022 struct disable_in_place_error_type
1023 {
1024 };
1025 using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
1026 using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
1027 using _value_type_ = devoid<value_type>;
1028 using _error_type_ = devoid<error_type>;
1029
1030 union
1031 {
1032 empty_type _empty1;
1033 _value_type_ _value;
1034 };
1035 status_bitfield_type _status;
1036 union
1037 {
1038 empty_type _empty2;
1039 _error_type_ _error;
1040 };
1041 #if __cplusplus >= 202000L || _HAS_CXX20
1042 constexpr
1043 #endif
1044 value_storage_nontrivial() noexcept
1045 : _empty1{}
1046 , _empty2{}
1047 {
1048 }
1049 value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default;
1050 value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default;
1051 #if __cplusplus >= 202000L || _HAS_CXX20
1052 constexpr
1053 #endif
1054 value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(std::is_nothrow_move_constructible<_value_type_>::value &&
1055 std::is_nothrow_move_constructible<_error_type_>::value)
1056 {
1057 if(o._status.have_value())
1058 {
1059 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value));
1060 }
1061 else if(o._status.have_error())
1062 {
1063 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error));
1064 }
1065 _status = o._status;
1066 o._status.set_have_moved_from(true);
1067 }
1068 #if __cplusplus >= 202000L || _HAS_CXX20
1069 constexpr
1070 #endif
1071 value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(std::is_nothrow_copy_constructible<_value_type_>::value &&
1072 std::is_nothrow_copy_constructible<_error_type_>::value)
1073 {
1074 if(o._status.have_value())
1075 {
1076 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(o._value);
1077 }
1078 else if(o._status.have_error())
1079 {
1080 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(o._error);
1081 }
1082 _status = o._status;
1083 }
1084 #if __cplusplus >= 202000L || _HAS_CXX20
1085 constexpr
1086 #endif
1087 explicit value_storage_nontrivial(status_bitfield_type status)
1088 : _empty1()
1089 , _status(status)
1090 , _empty2()
1091 {
1092 }
1093 template <class... Args>
1094 constexpr explicit value_storage_nontrivial(in_place_type_t<_value_type> ,
1095 Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
1096 : _value(static_cast<Args &&>(args)...)
1097 , _status(status::have_value)
1098 {
1099 }
1100 template <class U, class... Args>
1101 constexpr value_storage_nontrivial(in_place_type_t<_value_type> , std::initializer_list<U> il,
1102 Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
1103 : _value(il, static_cast<Args &&>(args)...)
1104 , _status(status::have_value)
1105 {
1106 }
1107 template <class... Args>
1108 constexpr explicit value_storage_nontrivial(in_place_type_t<_error_type> ,
1109 Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
1110 : _status(status::have_error)
1111 , _error(static_cast<Args &&>(args)...)
1112 {
1113 _set_error_is_errno(*this);
1114 }
1115 template <class U, class... Args>
1116 constexpr value_storage_nontrivial(in_place_type_t<_error_type> , std::initializer_list<U> il,
1117 Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
1118 : _status(status::have_error)
1119 , _error(il, static_cast<Args &&>(args)...)
1120 {
1121 _set_error_is_errno(*this);
1122 }
1123
1124 struct nonvoid_converting_constructor_tag
1125 {
1126 };
1127 template <class U, class V>
1128 static constexpr bool enable_nonvoid_converting_constructor =
1129 !(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value)
1130 && detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
1131 BOOST_OUTCOME_TEMPLATE(class U, class V)
1132 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
1133 constexpr explicit value_storage_nontrivial(const value_storage_trivial<U, V> &o, nonvoid_converting_constructor_tag = {}) noexcept(
1134 detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
1135 : value_storage_nontrivial(o._status.have_value() ?
1136 value_storage_nontrivial(in_place_type<value_type>, o._value) :
1137 (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
1138 {
1139 _status = o._status;
1140 }
1141 BOOST_OUTCOME_TEMPLATE(class U, class V)
1142 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
1143 constexpr explicit value_storage_nontrivial(value_storage_trivial<U, V> &&o, nonvoid_converting_constructor_tag = {}) noexcept(
1144 detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
1145 : value_storage_nontrivial(
1146 o._status.have_value() ?
1147 value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
1148 (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
1149 {
1150 _status = o._status;
1151 }
1152 BOOST_OUTCOME_TEMPLATE(class U, class V)
1153 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
1154 constexpr explicit value_storage_nontrivial(const value_storage_nontrivial<U, V> &o, nonvoid_converting_constructor_tag = {}) noexcept(
1155 detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
1156 : value_storage_nontrivial(o._status.have_value() ?
1157 value_storage_nontrivial(in_place_type<value_type>, o._value) :
1158 (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
1159 {
1160 _status = o._status;
1161 }
1162 BOOST_OUTCOME_TEMPLATE(class U, class V)
1163 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
1164 constexpr explicit value_storage_nontrivial(value_storage_nontrivial<U, V> &&o, nonvoid_converting_constructor_tag = {}) noexcept(
1165 detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
1166 : value_storage_nontrivial(
1167 o._status.have_value() ?
1168 value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
1169 (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
1170 {
1171 _status = o._status;
1172 }
1173
1174 struct void_value_converting_constructor_tag
1175 {
1176 };
1177 template <class V>
1178 static constexpr bool enable_void_value_converting_constructor =
1179 std::is_default_constructible<value_type>::value && detail::is_constructible<error_type, V>;
1180 BOOST_OUTCOME_TEMPLATE(class V)
1181 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
1182 constexpr explicit value_storage_nontrivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag = {}) noexcept(
1183 std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
1184 {
1185 if(o._status.have_value())
1186 {
1187 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_();
1188 }
1189 else if(o._status.have_error())
1190 {
1191 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(o._error);
1192 }
1193 _status = o._status;
1194 }
1195 BOOST_OUTCOME_TEMPLATE(class V)
1196 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
1197 constexpr explicit value_storage_nontrivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag = {}) noexcept(
1198 std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
1199 {
1200 if(o._status.have_value())
1201 {
1202 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_();
1203 }
1204 else if(o._status.have_error())
1205 {
1206 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error));
1207 }
1208 _status = o._status;
1209 o._status.set_have_moved_from(true);
1210 }
1211
1212 struct void_error_converting_constructor_tag
1213 {
1214 };
1215 template <class U>
1216 static constexpr bool enable_void_error_converting_constructor =
1217 std::is_default_constructible<error_type>::value && detail::is_constructible<value_type, U>;
1218 BOOST_OUTCOME_TEMPLATE(class U)
1219 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
1220 constexpr explicit value_storage_nontrivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag = {}) noexcept(
1221 detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
1222 {
1223 if(o._status.have_value())
1224 {
1225 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(o._value);
1226 }
1227 else if(o._status.have_error())
1228 {
1229 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_();
1230 }
1231 _status = o._status;
1232 }
1233 BOOST_OUTCOME_TEMPLATE(class U)
1234 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
1235 constexpr explicit value_storage_nontrivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag = {}) noexcept(
1236 detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
1237 {
1238 if(o._status.have_value())
1239 {
1240 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value));
1241 }
1242 else if(o._status.have_error())
1243 {
1244 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_();
1245 }
1246 _status = o._status;
1247 o._status.set_have_moved_from(true);
1248 }
1249
1250 #if __cplusplus >= 202000L || _HAS_CXX20
1251 constexpr
1252 #endif
1253 ~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<_value_type_>::value && std::is_nothrow_destructible<_error_type_>::value)
1254 {
1255 if(this->_status.have_value())
1256 {
1257 if(!trait::is_move_bitcopying<value_type>::value || !this->_status.have_moved_from())
1258 {
1259 this->_value.~_value_type_();
1260 }
1261 this->_status.set_have_value(false);
1262 }
1263 else if(this->_status.have_error())
1264 {
1265 if(!trait::is_move_bitcopying<error_type>::value || !this->_status.have_moved_from())
1266 {
1267 this->_error.~_error_type_();
1268 }
1269 this->_status.set_have_error(false);
1270 }
1271 }
1272 #if __cplusplus >= 202000L || _HAS_CXX20
1273 constexpr
1274 #endif
1275 void
1276 swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<_value_type_>::value && detail::is_nothrow_swappable<_error_type_>::value)
1277 {
1278 using std::swap;
1279
1280 if(!_status.have_value() && !o._status.have_value() && !_status.have_error() && !o._status.have_error())
1281 {
1282 swap(_status, o._status);
1283 return;
1284 }
1285
1286 if(_status.have_value() && o._status.have_value())
1287 {
1288 struct some_type
1289 {
1290 status_bitfield_type &a, &b;
1291 bool all_good{false};
1292 ~some_type()
1293 {
1294 if(!this->all_good)
1295 {
1296
1297 this->a.set_have_lost_consistency(true);
1298 this->b.set_have_lost_consistency(true);
1299 }
1300 }
1301 } some_type_value{_status, o._status};
1302 strong_swap(some_type_value.all_good, _value, o._value);
1303 swap(_status, o._status);
1304 return;
1305 }
1306
1307 if(_status.have_error() && o._status.have_error())
1308 {
1309 struct some_type
1310 {
1311 status_bitfield_type &a, &b;
1312 bool all_good{false};
1313 ~some_type()
1314 {
1315 if(!this->all_good)
1316 {
1317
1318 this->a.set_have_lost_consistency(true);
1319 this->b.set_have_lost_consistency(true);
1320 }
1321 }
1322 } some_type_value{_status, o._status};
1323 strong_swap(some_type_value.all_good, _error, o._error);
1324 swap(_status, o._status);
1325 return;
1326 }
1327
1328 if(_status.have_value() && !o._status.have_error())
1329 {
1330
1331 new(BOOST_OUTCOME_ADDRESS_OF(o._value)) _value_type_(static_cast<_value_type_ &&>(_value));
1332 if(!trait::is_move_bitcopying<value_type>::value)
1333 {
1334 this->_value.~value_type();
1335 }
1336 swap(_status, o._status);
1337 return;
1338 }
1339 if(o._status.have_value() && !_status.have_error())
1340 {
1341
1342 new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value));
1343 if(!trait::is_move_bitcopying<value_type>::value)
1344 {
1345 o._value.~value_type();
1346 }
1347 swap(_status, o._status);
1348 return;
1349 }
1350 if(_status.have_error() && !o._status.have_value())
1351 {
1352
1353 new(BOOST_OUTCOME_ADDRESS_OF(o._error)) _error_type_(static_cast<_error_type_ &&>(_error));
1354 if(!trait::is_move_bitcopying<error_type>::value)
1355 {
1356 this->_error.~error_type();
1357 }
1358 swap(_status, o._status);
1359 return;
1360 }
1361 if(o._status.have_error() && !_status.have_value())
1362 {
1363
1364 new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error));
1365 if(!trait::is_move_bitcopying<error_type>::value)
1366 {
1367 o._error.~error_type();
1368 }
1369 swap(_status, o._status);
1370 return;
1371 }
1372
1373 struct some_type
1374 {
1375 status_bitfield_type &a, &b;
1376 _value_type_ *value, *o_value;
1377 _error_type_ *error, *o_error;
1378 bool all_good{true};
1379 ~some_type()
1380 {
1381 if(!this->all_good)
1382 {
1383
1384 this->a.set_have_lost_consistency(true);
1385 this->b.set_have_lost_consistency(true);
1386 }
1387 }
1388 } some_type_value{_status, o._status, BOOST_OUTCOME_ADDRESS_OF(_value), BOOST_OUTCOME_ADDRESS_OF(o._value), BOOST_OUTCOME_ADDRESS_OF(_error), BOOST_OUTCOME_ADDRESS_OF(o._error)};
1389 if(_status.have_value() && o._status.have_error())
1390 {
1391 strong_placement(some_type_value.all_good, some_type_value.o_value, some_type_value.value, [&some_type_value] {
1392 strong_placement(some_type_value.all_good, some_type_value.error, some_type_value.o_error, [&some_type_value] {
1393 swap(some_type_value.a, some_type_value.b);
1394 });
1395 });
1396 return;
1397 }
1398 if(_status.have_error() && o._status.have_value())
1399 {
1400 strong_placement(some_type_value.all_good, some_type_value.o_error, some_type_value.error, [&some_type_value] {
1401 strong_placement(some_type_value.all_good, some_type_value.value, some_type_value.o_value, [&some_type_value] {
1402 swap(some_type_value.a, some_type_value.b);
1403 });
1404 });
1405 return;
1406 }
1407
1408 make_ub(_value);
1409 }
1410 };
1411 template <class Base> struct value_storage_delete_copy_constructor : Base
1412 {
1413 using Base::Base;
1414 using value_type = typename Base::value_type;
1415 using error_type = typename Base::error_type;
1416 value_storage_delete_copy_constructor() = default;
1417 value_storage_delete_copy_constructor(const value_storage_delete_copy_constructor &) = delete;
1418 value_storage_delete_copy_constructor(value_storage_delete_copy_constructor &&) = default;
1419 value_storage_delete_copy_constructor &operator=(const value_storage_delete_copy_constructor &o) = default;
1420 value_storage_delete_copy_constructor &operator=(value_storage_delete_copy_constructor &&o) = default;
1421 ~value_storage_delete_copy_constructor() = default;
1422 };
1423 template <class Base> struct value_storage_delete_copy_assignment : Base
1424 {
1425 using Base::Base;
1426 using value_type = typename Base::value_type;
1427 using error_type = typename Base::error_type;
1428 value_storage_delete_copy_assignment() = default;
1429 value_storage_delete_copy_assignment(const value_storage_delete_copy_assignment &) = default;
1430 value_storage_delete_copy_assignment(value_storage_delete_copy_assignment &&) = default;
1431 value_storage_delete_copy_assignment &operator=(const value_storage_delete_copy_assignment &o) = delete;
1432 value_storage_delete_copy_assignment &operator=(value_storage_delete_copy_assignment &&o) = default;
1433 ~value_storage_delete_copy_assignment() = default;
1434 };
1435 template <class Base> struct value_storage_delete_move_assignment : Base
1436 {
1437 using Base::Base;
1438 using value_type = typename Base::value_type;
1439 using error_type = typename Base::error_type;
1440 value_storage_delete_move_assignment() = default;
1441 value_storage_delete_move_assignment(const value_storage_delete_move_assignment &) = default;
1442 value_storage_delete_move_assignment(value_storage_delete_move_assignment &&) = default;
1443 value_storage_delete_move_assignment &operator=(const value_storage_delete_move_assignment &o) = default;
1444 value_storage_delete_move_assignment &operator=(value_storage_delete_move_assignment &&o) = delete;
1445 ~value_storage_delete_move_assignment() = default;
1446 };
1447 template <class Base> struct value_storage_delete_move_constructor : Base
1448 {
1449 using Base::Base;
1450 using value_type = typename Base::value_type;
1451 using error_type = typename Base::error_type;
1452 value_storage_delete_move_constructor() = default;
1453 value_storage_delete_move_constructor(const value_storage_delete_move_constructor &) = default;
1454 value_storage_delete_move_constructor(value_storage_delete_move_constructor &&) = delete;
1455 value_storage_delete_move_constructor &operator=(const value_storage_delete_move_constructor &o) = default;
1456 value_storage_delete_move_constructor &operator=(value_storage_delete_move_constructor &&o) = default;
1457 ~value_storage_delete_move_constructor() = default;
1458 };
1459 template <class Base> struct value_storage_nontrivial_move_assignment : Base
1460 {
1461 using Base::Base;
1462 using value_type = typename Base::value_type;
1463 using error_type = typename Base::error_type;
1464 value_storage_nontrivial_move_assignment() = default;
1465 value_storage_nontrivial_move_assignment(const value_storage_nontrivial_move_assignment &) = default;
1466 value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default;
1467 value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
1468 ~value_storage_nontrivial_move_assignment() = default;
1469 #if __cplusplus >= 202000L || _HAS_CXX20
1470 constexpr
1471 #endif
1472 value_storage_nontrivial_move_assignment &
1473 operator=(value_storage_nontrivial_move_assignment &&o) noexcept(std::is_nothrow_move_assignable<value_type>::value &&
1474 std::is_nothrow_move_assignable<error_type>::value &&
1475 noexcept(move_assign_to_empty<value_type>(static_cast<value_type *>(nullptr),
1476 static_cast<value_type *>(nullptr))) &&
1477 noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
1478 static_cast<error_type *>(nullptr))))
1479 {
1480 using _value_type_ = typename Base::_value_type_;
1481 using _error_type_ = typename Base::_error_type_;
1482 if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
1483 {
1484 this->_status = o._status;
1485 o._status.set_have_moved_from(true);
1486 return *this;
1487 }
1488 if(this->_status.have_value() && o._status.have_value())
1489 {
1490 this->_value = static_cast<_value_type_ &&>(o._value);
1491 this->_status = o._status;
1492 o._status.set_have_moved_from(true);
1493 return *this;
1494 }
1495 if(this->_status.have_error() && o._status.have_error())
1496 {
1497 this->_error = static_cast<_error_type_ &&>(o._error);
1498 this->_status = o._status;
1499 o._status.set_have_moved_from(true);
1500 return *this;
1501 }
1502 if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
1503 {
1504 if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
1505 {
1506 this->_value.~_value_type_();
1507 }
1508 this->_status = o._status;
1509 o._status.set_have_moved_from(true);
1510 return *this;
1511 }
1512 if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
1513 {
1514 move_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
1515 this->_status = o._status;
1516 o._status.set_have_moved_from(true);
1517 return *this;
1518 }
1519 if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
1520 {
1521 if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
1522 {
1523 this->_error.~_error_type_();
1524 }
1525 this->_status = o._status;
1526 o._status.set_have_moved_from(true);
1527 return *this;
1528 }
1529 if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
1530 {
1531 move_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
1532 this->_status = o._status;
1533 o._status.set_have_moved_from(true);
1534 return *this;
1535 }
1536 if(this->_status.have_value() && o._status.have_error())
1537 {
1538 if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
1539 {
1540 this->_value.~_value_type_();
1541 }
1542 move_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
1543 this->_status = o._status;
1544 o._status.set_have_moved_from(true);
1545 return *this;
1546 }
1547 if(this->_status.have_error() && o._status.have_value())
1548 {
1549 if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
1550 {
1551 this->_error.~_error_type_();
1552 }
1553 move_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
1554 this->_status = o._status;
1555 o._status.set_have_moved_from(true);
1556 return *this;
1557 }
1558
1559 make_ub(this->_value);
1560 }
1561 };
1562 template <class Base> struct value_storage_nontrivial_copy_assignment : Base
1563 {
1564 using Base::Base;
1565 using value_type = typename Base::value_type;
1566 using error_type = typename Base::error_type;
1567 value_storage_nontrivial_copy_assignment() = default;
1568 value_storage_nontrivial_copy_assignment(const value_storage_nontrivial_copy_assignment &) = default;
1569 value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default;
1570 value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default;
1571 ~value_storage_nontrivial_copy_assignment() = default;
1572 #if __cplusplus >= 202000L || _HAS_CXX20
1573 constexpr
1574 #endif
1575 value_storage_nontrivial_copy_assignment &
1576 operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(
1577 std::is_nothrow_copy_assignable<value_type>::value && std::is_nothrow_copy_assignable<error_type>::value &&
1578 noexcept(copy_assign_to_empty<value_type>(static_cast<value_type *>(nullptr), static_cast<value_type *>(nullptr))) &&
1579 noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr), static_cast<error_type *>(nullptr))))
1580 {
1581 using _value_type_ = typename Base::_value_type_;
1582 using _error_type_ = typename Base::_error_type_;
1583 if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
1584 {
1585 this->_status = o._status;
1586 return *this;
1587 }
1588 if(this->_status.have_value() && o._status.have_value())
1589 {
1590 this->_value = o._value;
1591 this->_status = o._status;
1592 return *this;
1593 }
1594 if(this->_status.have_error() && o._status.have_error())
1595 {
1596 this->_error = o._error;
1597 this->_status = o._status;
1598 return *this;
1599 }
1600 if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
1601 {
1602 if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
1603 {
1604 this->_value.~_value_type_();
1605 }
1606 this->_status = o._status;
1607 return *this;
1608 }
1609 if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
1610 {
1611 copy_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
1612 this->_status = o._status;
1613 return *this;
1614 }
1615 if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
1616 {
1617 if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
1618 {
1619 this->_error.~_error_type_();
1620 }
1621 this->_status = o._status;
1622 return *this;
1623 }
1624 if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
1625 {
1626 copy_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
1627 this->_status = o._status;
1628 return *this;
1629 }
1630 if(this->_status.have_value() && o._status.have_error())
1631 {
1632 if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
1633 {
1634 this->_value.~_value_type_();
1635 }
1636 copy_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
1637 this->_status = o._status;
1638 return *this;
1639 }
1640 if(this->_status.have_error() && o._status.have_value())
1641 {
1642 if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
1643 {
1644 this->_error.~_error_type_();
1645 }
1646 copy_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
1647 this->_status = o._status;
1648 return *this;
1649 }
1650
1651 make_ub(this->_value);
1652 }
1653 };
1654 #ifdef _MSC_VER
1655 #pragma warning(pop)
1656 #endif
1657
1658
1659 template <class T> struct is_storage_trivial
1660 {
1661 static constexpr bool value = std::is_void<T>::value || (std::is_trivially_copy_constructible<T>::value && std::is_trivially_copyable<T>::value);
1662 };
1663
1664 template <> struct is_storage_trivial<void>
1665 {
1666 static constexpr bool value = true;
1667 };
1668 template <> struct is_storage_trivial<const void>
1669 {
1670 static constexpr bool value = true;
1671 };
1672
1673 template <class T> struct is_copy_assignable
1674 {
1675 static constexpr bool value = std::is_copy_assignable<T>::value && (std::is_copy_constructible<T>::value || std::is_default_constructible<T>::value);
1676 };
1677
1678 template <class T> struct is_move_assignable
1679 {
1680 static constexpr bool value = std::is_move_assignable<T>::value && (std::is_move_constructible<T>::value || std::is_default_constructible<T>::value);
1681 };
1682
1683 template <class T, class E>
1684 using value_storage_select_trivality =
1685 std::conditional_t<is_storage_trivial<T>::value && is_storage_trivial<E>::value, value_storage_trivial<T, E>, value_storage_nontrivial<T, E>>;
1686 template <class T, class E>
1687 using value_storage_select_move_constructor =
1688 std::conditional_t<std::is_move_constructible<devoid<T>>::value && std::is_move_constructible<devoid<E>>::value, value_storage_select_trivality<T, E>,
1689 value_storage_delete_move_constructor<value_storage_select_trivality<T, E>>>;
1690 template <class T, class E>
1691 using value_storage_select_copy_constructor =
1692 std::conditional_t<std::is_copy_constructible<devoid<T>>::value && std::is_copy_constructible<devoid<E>>::value, value_storage_select_move_constructor<T, E>,
1693 value_storage_delete_copy_constructor<value_storage_select_move_constructor<T, E>>>;
1694 template <class T, class E>
1695 using value_storage_select_move_assignment =
1696 std::conditional_t<std::is_trivially_move_assignable<devoid<T>>::value && std::is_trivially_move_assignable<devoid<E>>::value,
1697 value_storage_select_copy_constructor<T, E>,
1698 std::conditional_t<is_move_assignable<devoid<T>>::value && is_move_assignable<devoid<E>>::value,
1699 value_storage_nontrivial_move_assignment<value_storage_select_copy_constructor<T, E>>,
1700 value_storage_delete_move_assignment<value_storage_select_copy_constructor<T, E>>>>;
1701 template <class T, class E>
1702 using value_storage_select_copy_assignment =
1703 std::conditional_t<std::is_trivially_copy_assignable<devoid<T>>::value && std::is_trivially_copy_assignable<devoid<E>>::value,
1704 value_storage_select_move_assignment<T, E>,
1705 std::conditional_t<is_copy_assignable<devoid<T>>::value && is_copy_assignable<devoid<E>>::value,
1706 value_storage_nontrivial_copy_assignment<value_storage_select_move_assignment<T, E>>,
1707 value_storage_delete_copy_assignment<value_storage_select_move_assignment<T, E>>>>;
1708 template <class T, class E> using value_storage_select_impl = value_storage_select_copy_assignment<T, E>;
1709 #ifndef NDEBUG
1710
1711
1712
1713
1714 static_assert(std::is_trivially_copyable<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivially copyable!");
1715 static_assert(std::is_trivially_assignable<value_storage_select_impl<int, long>, value_storage_select_impl<int, long>>::value,
1716 "value_storage_select_impl<int, long> is not trivially assignable!");
1717 static_assert(std::is_trivially_destructible<value_storage_select_impl<int, long>>::value,
1718 "value_storage_select_impl<int, long> is not trivially destructible!");
1719 static_assert(std::is_trivially_copy_constructible<value_storage_select_impl<int, long>>::value,
1720 "value_storage_select_impl<int, long> is not trivially copy constructible!");
1721 static_assert(std::is_trivially_move_constructible<value_storage_select_impl<int, long>>::value,
1722 "value_storage_select_impl<int, long> is not trivially move constructible!");
1723 static_assert(std::is_trivially_copy_assignable<value_storage_select_impl<int, long>>::value,
1724 "value_storage_select_impl<int, long> is not trivially copy assignable!");
1725 static_assert(std::is_trivially_move_assignable<value_storage_select_impl<int, long>>::value,
1726 "value_storage_select_impl<int, long> is not trivially move assignable!");
1727
1728 static_assert(std::is_standard_layout<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not a standard layout type!");
1729 #endif
1730 }
1731
1732 BOOST_OUTCOME_V2_NAMESPACE_END
1733
1734 #endif