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