value_storage.hpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734
  1. /* Essentially an internal optional implementation :)
  2. (C) 2017-2024 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
  3. File Created: June 2017
  4. Boost Software License - Version 1.0 - August 17th, 2003
  5. Permission is hereby granted, free of charge, to any person or organization
  6. obtaining a copy of the software and accompanying documentation covered by
  7. this license (the "Software") to use, reproduce, display, distribute,
  8. execute, and transmit the Software, and to prepare derivative works of the
  9. Software, and to permit third-parties to whom the Software is furnished to
  10. do so, all subject to the following:
  11. The copyright notices in the Software and this entire statement, including
  12. the above license grant, this restriction and the following disclaimer,
  13. must be included in all copies of the Software, in whole or in part, and
  14. all derivative works of the Software, unless such copies or derivative
  15. works are solely in the form of machine-executable object code generated by
  16. a source language processor.
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  20. SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  21. FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  22. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. DEALINGS IN THE SOFTWARE.
  24. */
  25. #ifndef BOOST_OUTCOME_VALUE_STORAGE_HPP
  26. #define BOOST_OUTCOME_VALUE_STORAGE_HPP
  27. #include "../config.hpp"
  28. BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
  29. namespace detail
  30. {
  31. // Helpers for move assigning to empty storage
  32. template <class T, bool isCopyOrMoveConstructible = std::is_copy_constructible<T>::value || std::is_move_constructible<T>::value,
  33. bool isDefaultConstructibleAndCopyOrMoveAssignable =
  34. std::is_default_constructible<T>::value && (std::is_copy_assignable<T>::value || std::is_move_assignable<T>::value)>
  35. struct move_assign_to_empty;
  36. // Prefer to use move or copy construction
  37. template <class T> struct move_assign_to_empty<T, true, false>
  38. {
  39. move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
  40. };
  41. template <class T> struct move_assign_to_empty<T, true, true>
  42. {
  43. move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_move_constructible<T>::value) { new(dest) T(static_cast<T &&>(*o)); }
  44. };
  45. // But fall back on default construction and move assign if necessary
  46. template <class T> struct move_assign_to_empty<T, false, true>
  47. {
  48. move_assign_to_empty(T *dest, T *o) noexcept(std::is_nothrow_default_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
  49. {
  50. new(dest) T;
  51. *dest = static_cast<T &&>(*o);
  52. }
  53. };
  54. // Void does nothing
  55. template <> struct move_assign_to_empty<void, false, false>
  56. {
  57. move_assign_to_empty(void *, void *) noexcept { /* nothing to assign */ }
  58. };
  59. template <> struct move_assign_to_empty<const void, false, false>
  60. {
  61. move_assign_to_empty(const void *, const void *) noexcept { /* nothing to assign */ }
  62. };
  63. // Helpers for copy assigning to empty storage
  64. template <class T, bool isCopyConstructible = std::is_copy_constructible<T>::value,
  65. bool isDefaultConstructibleAndCopyAssignable = std::is_default_constructible<T>::value && std::is_copy_assignable<T>::value>
  66. struct copy_assign_to_empty;
  67. // Prefer to use copy construction
  68. template <class T> struct copy_assign_to_empty<T, true, false>
  69. {
  70. copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
  71. };
  72. template <class T> struct copy_assign_to_empty<T, true, true>
  73. {
  74. copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_copy_constructible<T>::value) { new(dest) T(*o); }
  75. };
  76. // But fall back on default construction and copy assign if necessary
  77. template <class T> struct copy_assign_to_empty<T, false, true>
  78. {
  79. copy_assign_to_empty(T *dest, const T *o) noexcept(std::is_nothrow_default_constructible<T>::value && std::is_nothrow_copy_assignable<T>::value)
  80. {
  81. new(dest) T;
  82. *dest = *o;
  83. }
  84. };
  85. // Void does nothing
  86. template <> struct copy_assign_to_empty<void, false, false>
  87. {
  88. copy_assign_to_empty(void *, void *) noexcept { /* nothing to assign */ }
  89. };
  90. template <> struct copy_assign_to_empty<const void, false, false>
  91. {
  92. copy_assign_to_empty(const void *, const void *) noexcept { /* nothing to assign */ }
  93. };
  94. template <class T, bool nothrow> struct strong_swap_impl
  95. {
  96. constexpr strong_swap_impl(bool &allgood, T &a, T &b)
  97. {
  98. allgood = true;
  99. using std::swap;
  100. swap(a, b);
  101. }
  102. };
  103. template <class T, bool nothrow> struct strong_placement_impl
  104. {
  105. template <class F> constexpr strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
  106. {
  107. allgood = true;
  108. new(a) T(static_cast<T &&>(*b));
  109. b->~T();
  110. f();
  111. }
  112. };
  113. #ifndef BOOST_NO_EXCEPTIONS
  114. template <class T> struct strong_swap_impl<T, false>
  115. {
  116. strong_swap_impl(bool &allgood, T &a, T &b)
  117. {
  118. allgood = true;
  119. T v(static_cast<T &&>(a));
  120. try
  121. {
  122. a = static_cast<T &&>(b);
  123. }
  124. catch(...)
  125. {
  126. // Try to put back a
  127. try
  128. {
  129. a = static_cast<T &&>(v);
  130. // fall through as all good
  131. }
  132. catch(...)
  133. {
  134. // failed to completely restore
  135. allgood = false;
  136. // throw away second exception
  137. }
  138. throw; // rethrow original exception
  139. }
  140. // b has been moved to a, try to move v to b
  141. try
  142. {
  143. b = static_cast<T &&>(v);
  144. }
  145. catch(...)
  146. {
  147. // Try to restore a to b, and v to a
  148. try
  149. {
  150. b = static_cast<T &&>(a);
  151. a = static_cast<T &&>(v);
  152. // fall through as all good
  153. }
  154. catch(...)
  155. {
  156. // failed to completely restore
  157. allgood = false;
  158. // throw away second exception
  159. }
  160. throw; // rethrow original exception
  161. }
  162. }
  163. };
  164. template <class T> struct strong_placement_impl<T, false>
  165. {
  166. template <class F> strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
  167. {
  168. new(a) T(static_cast<T &&>(*b));
  169. try
  170. {
  171. b->~T();
  172. f();
  173. }
  174. catch(...)
  175. {
  176. // Try to put back a, but only if we are still good
  177. if(allgood)
  178. {
  179. try
  180. {
  181. new(b) T(static_cast<T &&>(*a));
  182. // fall through as all good
  183. }
  184. catch(...)
  185. {
  186. // failed to completely restore
  187. allgood = false;
  188. // throw away second exception
  189. }
  190. throw; // rethrow original exception
  191. }
  192. }
  193. }
  194. };
  195. #endif
  196. } // namespace detail
  197. /*!
  198. */
  199. BOOST_OUTCOME_TEMPLATE(class T)
  200. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
  201. constexpr inline void strong_swap(bool &allgood, T &a, T &b) noexcept(detail::is_nothrow_swappable<T>::value)
  202. {
  203. detail::strong_swap_impl<T, detail::is_nothrow_swappable<T>::value>(allgood, a, b);
  204. }
  205. /*!
  206. */
  207. BOOST_OUTCOME_TEMPLATE(class T, class F)
  208. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
  209. constexpr inline void strong_placement(bool &allgood, T *a, T *b, F &&f) noexcept(std::is_nothrow_move_constructible<T>::value)
  210. {
  211. detail::strong_placement_impl<T, std::is_nothrow_move_constructible<T>::value>(allgood, a, b, static_cast<F &&>(f));
  212. }
  213. namespace detail
  214. {
  215. template <class T>
  216. constexpr
  217. #ifdef _MSC_VER
  218. __declspec(noreturn)
  219. #elif defined(__GNUC__) || defined(__clang__)
  220. __attribute__((noreturn))
  221. #endif
  222. void
  223. make_ub(T && /*unused*/)
  224. {
  225. BOOST_OUTCOME_ASSERT(false); // NOLINT
  226. #if defined(__GNUC__) || defined(__clang__)
  227. __builtin_unreachable();
  228. #elif defined(_MSC_VER)
  229. __assume(0);
  230. #endif
  231. }
  232. /* Outcome v1 used a C bitfield whose values were tracked by compiler optimisers nicely,
  233. but that produces ICEs when used in constexpr.
  234. Outcome v2.0-v2.1 used a 32 bit integer and manually set and cleared bits. Unfortunately
  235. only GCC's optimiser tracks bit values during constant folding, and only per byte, and
  236. even then unreliably. https://wg21.link/P1886 "Error speed benchmarking" showed just how
  237. poorly clang and MSVC fails to optimise outcome-using code, if you manually set bits.
  238. Outcome v2.2 therefore uses an enum with fixed values, and constexpr manipulation functions
  239. to change the value to one of the enum's values. This is stupid to look at in source code,
  240. but it make clang's optimiser do the right thing, so it's worth it.
  241. */
  242. #define BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS 0
  243. enum class status : uint16_t
  244. {
  245. // WARNING: These bits are not tracked by abi-dumper, but changing them will break ABI!
  246. none = 0,
  247. have_value = (1U << 0U),
  248. have_error = (1U << 1U),
  249. have_exception = (2U << 1U),
  250. have_error_exception = (3U << 1U),
  251. // failed to complete a strong swap
  252. have_lost_consistency = (1U << 3U),
  253. have_value_lost_consistency = (1U << 0U) | (1U << 3U),
  254. have_error_lost_consistency = (1U << 1U) | (1U << 3U),
  255. have_exception_lost_consistency = (2U << 1U) | (1U << 3U),
  256. have_error_exception_lost_consistency = (3U << 1U) | (1U << 3U),
  257. // can errno be set from this error?
  258. have_error_is_errno = (1U << 4U),
  259. have_error_error_is_errno = (1U << 1U) | (1U << 4U),
  260. have_error_exception_error_is_errno = (3U << 1U) | (1U << 4U),
  261. have_error_lost_consistency_error_is_errno = (1U << 1U) | (1U << 3U) | (1U << 4U),
  262. have_error_exception_lost_consistency_error_is_errno = (3U << 1U) | (1U << 3U) | (1U << 4U),
  263. // value has been moved from
  264. have_moved_from = (1U << 5U)
  265. };
  266. struct status_bitfield_type
  267. {
  268. status status_value{status::none};
  269. uint16_t spare_storage_value{0}; // hooks::spare_storage()
  270. constexpr status_bitfield_type() = default;
  271. constexpr status_bitfield_type(status v) noexcept
  272. : status_value(v)
  273. {
  274. } // NOLINT
  275. constexpr status_bitfield_type(status v, uint16_t s) noexcept
  276. : status_value(v)
  277. , spare_storage_value(s)
  278. {
  279. }
  280. constexpr status_bitfield_type(const status_bitfield_type &) = default;
  281. constexpr status_bitfield_type(status_bitfield_type &&) = default;
  282. constexpr status_bitfield_type &operator=(const status_bitfield_type &) = default;
  283. constexpr status_bitfield_type &operator=(status_bitfield_type &&) = default;
  284. //~status_bitfield_type() = default; // Do NOT uncomment this, it breaks older clangs!
  285. constexpr bool have_value() const noexcept
  286. {
  287. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  288. return (status_value == status::have_value) //
  289. || (status_value == status::have_value_lost_consistency) //
  290. ;
  291. #else
  292. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_value)) != 0;
  293. #endif
  294. }
  295. constexpr bool have_error() const noexcept
  296. {
  297. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  298. return (status_value == status::have_error) //
  299. || (status_value == status::have_error_exception) //
  300. || (status_value == status::have_error_lost_consistency) //
  301. || (status_value == status::have_error_exception_lost_consistency) //
  302. || (status_value == status::have_error_error_is_errno) //
  303. || (status_value == status::have_error_exception_error_is_errno) //
  304. || (status_value == status::have_error_lost_consistency_error_is_errno) //
  305. || (status_value == status::have_error_exception_lost_consistency_error_is_errno) //
  306. ;
  307. #else
  308. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error)) != 0;
  309. #endif
  310. }
  311. constexpr bool have_exception() const noexcept
  312. {
  313. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  314. return (status_value == status::have_exception) //
  315. || (status_value == status::have_error_exception) //
  316. || (status_value == status::have_exception_lost_consistency) //
  317. || (status_value == status::have_error_exception_lost_consistency) //
  318. || (status_value == status::have_error_exception_error_is_errno) //
  319. || (status_value == status::have_error_exception_lost_consistency_error_is_errno) //
  320. ;
  321. #else
  322. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_exception)) != 0;
  323. #endif
  324. }
  325. constexpr bool have_lost_consistency() const noexcept
  326. {
  327. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  328. return (status_value == status::have_value_lost_consistency) //
  329. || (status_value == status::have_error_lost_consistency) //
  330. || (status_value == status::have_exception_lost_consistency) //
  331. || (status_value == status::have_error_lost_consistency_error_is_errno) //
  332. || (status_value == status::have_error_exception_lost_consistency_error_is_errno) //
  333. ;
  334. #else
  335. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_lost_consistency)) != 0;
  336. #endif
  337. }
  338. constexpr bool have_error_is_errno() const noexcept
  339. {
  340. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  341. return (status_value == status::have_error_error_is_errno) //
  342. || (status_value == status::have_error_exception_error_is_errno) //
  343. || (status_value == status::have_error_lost_consistency_error_is_errno) //
  344. || (status_value == status::have_error_exception_lost_consistency_error_is_errno) //
  345. ;
  346. #else
  347. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error_is_errno)) != 0;
  348. #endif
  349. }
  350. constexpr bool have_moved_from() const noexcept
  351. {
  352. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  353. #error Fixme
  354. #else
  355. return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_moved_from)) != 0;
  356. #endif
  357. }
  358. constexpr status_bitfield_type &set_have_value(bool v) noexcept
  359. {
  360. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  361. switch(status_value)
  362. {
  363. case status::none:
  364. if(v)
  365. {
  366. status_value = status::have_value;
  367. }
  368. break;
  369. case status::have_value:
  370. if(!v)
  371. {
  372. status_value = status::none;
  373. }
  374. break;
  375. case status::have_error:
  376. if(v)
  377. {
  378. make_ub(*this);
  379. }
  380. break;
  381. case status::have_exception:
  382. if(v)
  383. {
  384. make_ub(*this);
  385. }
  386. break;
  387. case status::have_error_exception:
  388. if(v)
  389. {
  390. make_ub(*this);
  391. }
  392. break;
  393. case status::have_value_lost_consistency:
  394. if(!v)
  395. {
  396. status_value = status::none;
  397. }
  398. break;
  399. case status::have_error_lost_consistency:
  400. if(v)
  401. {
  402. make_ub(*this);
  403. }
  404. break;
  405. case status::have_exception_lost_consistency:
  406. if(v)
  407. {
  408. make_ub(*this);
  409. }
  410. break;
  411. case status::have_error_exception_lost_consistency:
  412. if(v)
  413. {
  414. make_ub(*this);
  415. }
  416. break;
  417. case status::have_error_error_is_errno:
  418. if(v)
  419. {
  420. make_ub(*this);
  421. }
  422. break;
  423. case status::have_error_exception_error_is_errno:
  424. if(v)
  425. {
  426. make_ub(*this);
  427. }
  428. break;
  429. case status::have_error_lost_consistency_error_is_errno:
  430. if(v)
  431. {
  432. make_ub(*this);
  433. }
  434. break;
  435. case status::have_error_exception_lost_consistency_error_is_errno:
  436. if(v)
  437. {
  438. make_ub(*this);
  439. }
  440. break;
  441. }
  442. #else
  443. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_value)) :
  444. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_value)));
  445. #endif
  446. return *this;
  447. }
  448. constexpr status_bitfield_type &set_have_error(bool v) noexcept
  449. {
  450. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  451. switch(status_value)
  452. {
  453. case status::none:
  454. if(v)
  455. {
  456. status_value = status::have_error;
  457. }
  458. break;
  459. case status::have_value:
  460. if(v)
  461. {
  462. make_ub(*this);
  463. }
  464. break;
  465. case status::have_error:
  466. if(!v)
  467. {
  468. status_value = status::none;
  469. }
  470. break;
  471. case status::have_exception:
  472. if(v)
  473. {
  474. status_value = status::have_error_exception;
  475. }
  476. break;
  477. case status::have_error_exception:
  478. if(!v)
  479. {
  480. status_value = status::have_exception;
  481. }
  482. break;
  483. case status::have_value_lost_consistency:
  484. if(v)
  485. {
  486. make_ub(*this);
  487. }
  488. break;
  489. case status::have_error_lost_consistency:
  490. if(!v)
  491. {
  492. status_value = status::none;
  493. }
  494. break;
  495. case status::have_exception_lost_consistency:
  496. if(v)
  497. {
  498. status_value = status::have_error_exception_lost_consistency;
  499. }
  500. break;
  501. case status::have_error_exception_lost_consistency:
  502. if(!v)
  503. {
  504. status_value = status::have_exception_lost_consistency;
  505. }
  506. break;
  507. case status::have_error_error_is_errno:
  508. if(!v)
  509. {
  510. status_value = status::none;
  511. }
  512. break;
  513. case status::have_error_exception_error_is_errno:
  514. if(!v)
  515. {
  516. status_value = status::have_exception;
  517. }
  518. break;
  519. case status::have_error_lost_consistency_error_is_errno:
  520. if(!v)
  521. {
  522. status_value = status::none;
  523. }
  524. break;
  525. case status::have_error_exception_lost_consistency_error_is_errno:
  526. if(!v)
  527. {
  528. status_value = status::have_exception_lost_consistency;
  529. }
  530. break;
  531. }
  532. #else
  533. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error)) :
  534. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error)));
  535. #endif
  536. return *this;
  537. }
  538. constexpr status_bitfield_type &set_have_exception(bool v) noexcept
  539. {
  540. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  541. switch(status_value)
  542. {
  543. case status::none:
  544. if(v)
  545. {
  546. status_value = status::have_exception;
  547. }
  548. break;
  549. case status::have_value:
  550. if(v)
  551. {
  552. make_ub(*this);
  553. }
  554. break;
  555. case status::have_error:
  556. if(v)
  557. {
  558. status_value = status::have_error_exception;
  559. }
  560. break;
  561. case status::have_exception:
  562. if(!v)
  563. {
  564. status_value = status::none;
  565. }
  566. break;
  567. case status::have_error_exception:
  568. if(!v)
  569. {
  570. status_value = status::have_error;
  571. }
  572. break;
  573. case status::have_value_lost_consistency:
  574. if(v)
  575. {
  576. make_ub(*this);
  577. }
  578. break;
  579. case status::have_error_lost_consistency:
  580. if(v)
  581. {
  582. status_value = status::have_error_exception_lost_consistency;
  583. }
  584. break;
  585. case status::have_exception_lost_consistency:
  586. if(!v)
  587. {
  588. status_value = status::none;
  589. }
  590. break;
  591. case status::have_error_exception_lost_consistency:
  592. if(!v)
  593. {
  594. status_value = status::have_error_lost_consistency;
  595. }
  596. break;
  597. case status::have_error_error_is_errno:
  598. if(v)
  599. {
  600. status_value = status::have_error_exception_error_is_errno;
  601. }
  602. break;
  603. case status::have_error_exception_error_is_errno:
  604. if(!v)
  605. {
  606. status_value = status::have_error_error_is_errno;
  607. }
  608. break;
  609. case status::have_error_lost_consistency_error_is_errno:
  610. if(v)
  611. {
  612. status_value = status::have_error_exception_lost_consistency_error_is_errno;
  613. }
  614. break;
  615. case status::have_error_exception_lost_consistency_error_is_errno:
  616. if(!v)
  617. {
  618. status_value = status::have_error_lost_consistency_error_is_errno;
  619. }
  620. break;
  621. }
  622. #else
  623. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_exception)) :
  624. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_exception)));
  625. #endif
  626. return *this;
  627. }
  628. constexpr status_bitfield_type &set_have_error_is_errno(bool v) noexcept
  629. {
  630. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  631. switch(status_value)
  632. {
  633. case status::none:
  634. make_ub(*this);
  635. break;
  636. case status::have_value:
  637. make_ub(*this);
  638. break;
  639. case status::have_error:
  640. if(v)
  641. {
  642. status_value = status::have_error_error_is_errno;
  643. }
  644. break;
  645. case status::have_exception:
  646. make_ub(*this);
  647. break;
  648. case status::have_error_exception:
  649. if(v)
  650. {
  651. status_value = status::have_error_exception_error_is_errno;
  652. }
  653. break;
  654. case status::have_value_lost_consistency:
  655. make_ub(*this);
  656. break;
  657. case status::have_error_lost_consistency:
  658. if(v)
  659. {
  660. status_value = status::have_error_lost_consistency_error_is_errno;
  661. }
  662. break;
  663. case status::have_exception_lost_consistency:
  664. make_ub(*this);
  665. break;
  666. case status::have_error_exception_lost_consistency:
  667. if(v)
  668. {
  669. status_value = status::have_error_exception_lost_consistency_error_is_errno;
  670. }
  671. break;
  672. case status::have_error_error_is_errno:
  673. if(!v)
  674. {
  675. status_value = status::have_error;
  676. }
  677. break;
  678. case status::have_error_exception_error_is_errno:
  679. if(!v)
  680. {
  681. status_value = status::have_error_exception;
  682. }
  683. break;
  684. case status::have_error_lost_consistency_error_is_errno:
  685. if(!v)
  686. {
  687. status_value = status::have_error_lost_consistency;
  688. }
  689. break;
  690. case status::have_error_exception_lost_consistency_error_is_errno:
  691. if(!v)
  692. {
  693. status_value = status::have_error_exception_lost_consistency;
  694. }
  695. break;
  696. }
  697. #else
  698. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error_is_errno)) :
  699. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error_is_errno)));
  700. #endif
  701. return *this;
  702. }
  703. constexpr status_bitfield_type &set_have_lost_consistency(bool v) noexcept
  704. {
  705. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  706. switch(status_value)
  707. {
  708. case status::none:
  709. if(v)
  710. {
  711. make_ub(*this);
  712. }
  713. break;
  714. case status::have_value:
  715. if(v)
  716. {
  717. status_value = status::have_value_lost_consistency;
  718. }
  719. break;
  720. case status::have_error:
  721. if(v)
  722. {
  723. status_value = status::have_error_lost_consistency;
  724. }
  725. break;
  726. case status::have_exception:
  727. if(v)
  728. {
  729. status_value = status::have_exception_lost_consistency;
  730. }
  731. break;
  732. case status::have_error_exception:
  733. if(v)
  734. {
  735. status_value = status::have_error_exception_lost_consistency;
  736. }
  737. break;
  738. case status::have_value_lost_consistency:
  739. if(!v)
  740. {
  741. status_value = status::have_value;
  742. }
  743. break;
  744. case status::have_error_lost_consistency:
  745. if(!v)
  746. {
  747. status_value = status::have_error;
  748. }
  749. break;
  750. case status::have_exception_lost_consistency:
  751. if(!v)
  752. {
  753. status_value = status::have_exception;
  754. }
  755. break;
  756. case status::have_error_exception_lost_consistency:
  757. if(!v)
  758. {
  759. status_value = status::have_error_exception;
  760. }
  761. break;
  762. case status::have_error_error_is_errno:
  763. if(v)
  764. {
  765. status_value = status::have_error_lost_consistency_error_is_errno;
  766. }
  767. break;
  768. case status::have_error_exception_error_is_errno:
  769. if(v)
  770. {
  771. status_value = status::have_error_exception_lost_consistency_error_is_errno;
  772. }
  773. break;
  774. case status::have_error_lost_consistency_error_is_errno:
  775. if(!v)
  776. {
  777. status_value = status::have_error_exception_error_is_errno;
  778. }
  779. break;
  780. case status::have_error_exception_lost_consistency_error_is_errno:
  781. if(!v)
  782. {
  783. status_value = status::have_error_exception_error_is_errno;
  784. }
  785. break;
  786. }
  787. #else
  788. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_lost_consistency)) :
  789. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_lost_consistency)));
  790. #endif
  791. return *this;
  792. }
  793. constexpr status_bitfield_type &set_have_moved_from(bool v) noexcept
  794. {
  795. #if BOOST_OUTCOME_USE_CONSTEXPR_ENUM_STATUS
  796. #error Fixme
  797. #else
  798. status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_moved_from)) :
  799. (static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_moved_from)));
  800. #endif
  801. return *this;
  802. }
  803. };
  804. #if !defined(NDEBUG)
  805. // Check is trivial in all ways except default constructibility
  806. static_assert(sizeof(status_bitfield_type) == 4, "status_bitfield_type is not sized 4 bytes!");
  807. static_assert(std::is_trivially_copyable<status_bitfield_type>::value, "status_bitfield_type is not trivially copyable!");
  808. static_assert(std::is_trivially_assignable<status_bitfield_type, status_bitfield_type>::value, "status_bitfield_type is not trivially assignable!");
  809. static_assert(std::is_trivially_destructible<status_bitfield_type>::value, "status_bitfield_type is not trivially destructible!");
  810. static_assert(std::is_trivially_copy_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially copy constructible!");
  811. static_assert(std::is_trivially_move_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially move constructible!");
  812. static_assert(std::is_trivially_copy_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially copy assignable!");
  813. static_assert(std::is_trivially_move_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially move assignable!");
  814. // Also check is standard layout
  815. static_assert(std::is_standard_layout<status_bitfield_type>::value, "status_bitfield_type is not a standard layout type!");
  816. #endif
  817. template <class State> constexpr inline void _set_error_is_errno(State & /*unused*/) {}
  818. #ifdef _MSC_VER
  819. #pragma warning(push)
  820. #pragma warning(disable : 4127) // conditional expression is constant
  821. #pragma warning(disable : 4624) // destructor was implicitly defined as deleted
  822. #endif
  823. // Used if both T and E are trivial
  824. template <class T, class E> struct value_storage_trivial
  825. {
  826. using value_type = T;
  827. using error_type = E;
  828. // Disable in place construction if they are the same type
  829. struct disable_in_place_value_type
  830. {
  831. };
  832. struct disable_in_place_error_type
  833. {
  834. };
  835. using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
  836. using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
  837. using _value_type_ = devoid<value_type>;
  838. using _error_type_ = devoid<error_type>;
  839. union
  840. {
  841. empty_type _empty;
  842. _value_type_ _value;
  843. _error_type_ _error;
  844. };
  845. status_bitfield_type _status;
  846. constexpr value_storage_trivial() noexcept
  847. : _empty{}
  848. {
  849. }
  850. value_storage_trivial(const value_storage_trivial &) = default; // NOLINT
  851. value_storage_trivial(value_storage_trivial &&) = default; // NOLINT
  852. value_storage_trivial &operator=(const value_storage_trivial &) = default; // NOLINT
  853. value_storage_trivial &operator=(value_storage_trivial &&) = default; // NOLINT
  854. ~value_storage_trivial() = default;
  855. constexpr explicit value_storage_trivial(status_bitfield_type status)
  856. : _empty()
  857. , _status(status)
  858. {
  859. }
  860. template <class... Args>
  861. constexpr explicit value_storage_trivial(in_place_type_t<_value_type> /*unused*/,
  862. Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
  863. : _value(static_cast<Args &&>(args)...)
  864. , _status(status::have_value)
  865. {
  866. }
  867. template <class U, class... Args>
  868. constexpr value_storage_trivial(in_place_type_t<_value_type> /*unused*/, std::initializer_list<U> il,
  869. Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
  870. : _value(il, static_cast<Args &&>(args)...)
  871. , _status(status::have_value)
  872. {
  873. }
  874. template <class... Args>
  875. constexpr explicit value_storage_trivial(in_place_type_t<_error_type> /*unused*/,
  876. Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
  877. : _error(static_cast<Args &&>(args)...)
  878. , _status(status::have_error)
  879. {
  880. _set_error_is_errno(*this);
  881. }
  882. template <class U, class... Args>
  883. constexpr value_storage_trivial(in_place_type_t<_error_type> /*unused*/, std::initializer_list<U> il,
  884. Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
  885. : _error(il, static_cast<Args &&>(args)...)
  886. , _status(status::have_error)
  887. {
  888. _set_error_is_errno(*this);
  889. }
  890. struct nonvoid_converting_constructor_tag
  891. {
  892. };
  893. template <class U, class V>
  894. static constexpr bool enable_nonvoid_converting_constructor =
  895. !(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value) //
  896. && detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
  897. BOOST_OUTCOME_TEMPLATE(class U, class V)
  898. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  899. constexpr explicit value_storage_trivial(const value_storage_trivial<U, V> &o,
  900. nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(detail::is_nothrow_constructible<_value_type_, U> &&
  901. detail::is_nothrow_constructible<_error_type_, V>)
  902. : value_storage_trivial(o._status.have_value() ?
  903. value_storage_trivial(in_place_type<value_type>, o._value) :
  904. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial())) // NOLINT
  905. {
  906. _status = o._status;
  907. }
  908. BOOST_OUTCOME_TEMPLATE(class U, class V)
  909. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  910. constexpr explicit value_storage_trivial(value_storage_trivial<U, V> &&o,
  911. nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(detail::is_nothrow_constructible<_value_type_, U> &&
  912. detail::is_nothrow_constructible<_error_type_, V>)
  913. : value_storage_trivial(
  914. o._status.have_value() ?
  915. value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
  916. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial())) // NOLINT
  917. {
  918. _status = o._status;
  919. }
  920. struct void_value_converting_constructor_tag
  921. {
  922. };
  923. template <class V>
  924. static constexpr bool enable_void_value_converting_constructor =
  925. std::is_default_constructible<value_type>::value && detail::is_constructible<error_type, V>;
  926. BOOST_OUTCOME_TEMPLATE(class V)
  927. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
  928. constexpr explicit value_storage_trivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
  929. std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
  930. : value_storage_trivial(o._status.have_value() ?
  931. value_storage_trivial(in_place_type<value_type>) :
  932. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial())) // NOLINT
  933. {
  934. _status = o._status;
  935. }
  936. BOOST_OUTCOME_TEMPLATE(class V)
  937. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
  938. constexpr explicit value_storage_trivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
  939. std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
  940. : value_storage_trivial(
  941. o._status.have_value() ?
  942. value_storage_trivial(in_place_type<value_type>) :
  943. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial())) // NOLINT
  944. {
  945. _status = o._status;
  946. }
  947. struct void_error_converting_constructor_tag
  948. {
  949. };
  950. template <class U>
  951. static constexpr bool enable_void_error_converting_constructor =
  952. std::is_default_constructible<error_type>::value && detail::is_constructible<value_type, U>;
  953. BOOST_OUTCOME_TEMPLATE(class U)
  954. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
  955. constexpr explicit value_storage_trivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
  956. detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
  957. : value_storage_trivial(o._status.have_value() ?
  958. value_storage_trivial(in_place_type<value_type>, o._value) :
  959. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial())) // NOLINT
  960. {
  961. _status = o._status;
  962. }
  963. BOOST_OUTCOME_TEMPLATE(class U)
  964. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
  965. constexpr explicit value_storage_trivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
  966. detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
  967. : value_storage_trivial(o._status.have_value() ?
  968. value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
  969. (o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial())) // NOLINT
  970. {
  971. _status = o._status;
  972. }
  973. constexpr void swap(value_storage_trivial &o) noexcept
  974. {
  975. // storage is trivial, so just use assignment
  976. auto temp = static_cast<value_storage_trivial &&>(*this);
  977. *this = static_cast<value_storage_trivial &&>(o);
  978. o = static_cast<value_storage_trivial &&>(temp);
  979. }
  980. };
  981. /* Used if T or E is non-trivial. The additional constexpr is injected in C++ 20 to enable Outcome to
  982. work in constexpr evaluation contexts in C++ 20 where non-trivial constexpr destructors are now allowed.
  983. */
  984. template <class T, class E> struct value_storage_nontrivial
  985. {
  986. using value_type = T;
  987. using error_type = E;
  988. struct disable_in_place_value_type
  989. {
  990. };
  991. struct disable_in_place_error_type
  992. {
  993. };
  994. using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
  995. using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
  996. using _value_type_ = devoid<value_type>;
  997. using _error_type_ = devoid<error_type>;
  998. union
  999. {
  1000. empty_type _empty1;
  1001. _value_type_ _value;
  1002. };
  1003. status_bitfield_type _status;
  1004. union
  1005. {
  1006. empty_type _empty2;
  1007. _error_type_ _error;
  1008. };
  1009. #if __cplusplus >= 202000L || _HAS_CXX20
  1010. constexpr
  1011. #endif
  1012. value_storage_nontrivial() noexcept
  1013. : _empty1{}
  1014. , _empty2{}
  1015. {
  1016. }
  1017. value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
  1018. value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
  1019. #if __cplusplus >= 202000L || _HAS_CXX20
  1020. constexpr
  1021. #endif
  1022. value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(std::is_nothrow_move_constructible<_value_type_>::value &&
  1023. std::is_nothrow_move_constructible<_error_type_>::value) // NOLINT
  1024. {
  1025. if(o._status.have_value())
  1026. {
  1027. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
  1028. }
  1029. else if(o._status.have_error())
  1030. {
  1031. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
  1032. }
  1033. _status = o._status;
  1034. o._status.set_have_moved_from(true);
  1035. }
  1036. #if __cplusplus >= 202000L || _HAS_CXX20
  1037. constexpr
  1038. #endif
  1039. value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(std::is_nothrow_copy_constructible<_value_type_>::value &&
  1040. std::is_nothrow_copy_constructible<_error_type_>::value)
  1041. {
  1042. if(o._status.have_value())
  1043. {
  1044. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(o._value); // NOLINT
  1045. }
  1046. else if(o._status.have_error())
  1047. {
  1048. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(o._error); // NOLINT
  1049. }
  1050. _status = o._status;
  1051. }
  1052. #if __cplusplus >= 202000L || _HAS_CXX20
  1053. constexpr
  1054. #endif
  1055. explicit value_storage_nontrivial(status_bitfield_type status)
  1056. : _empty1()
  1057. , _status(status)
  1058. , _empty2()
  1059. {
  1060. }
  1061. template <class... Args>
  1062. constexpr explicit value_storage_nontrivial(in_place_type_t<_value_type> /*unused*/,
  1063. Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
  1064. : _value(static_cast<Args &&>(args)...) // NOLINT
  1065. , _status(status::have_value)
  1066. {
  1067. }
  1068. template <class U, class... Args>
  1069. constexpr value_storage_nontrivial(in_place_type_t<_value_type> /*unused*/, std::initializer_list<U> il,
  1070. Args &&...args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
  1071. : _value(il, static_cast<Args &&>(args)...)
  1072. , _status(status::have_value)
  1073. {
  1074. }
  1075. template <class... Args>
  1076. constexpr explicit value_storage_nontrivial(in_place_type_t<_error_type> /*unused*/,
  1077. Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
  1078. : _status(status::have_error)
  1079. , _error(static_cast<Args &&>(args)...) // NOLINT
  1080. {
  1081. _set_error_is_errno(*this);
  1082. }
  1083. template <class U, class... Args>
  1084. constexpr value_storage_nontrivial(in_place_type_t<_error_type> /*unused*/, std::initializer_list<U> il,
  1085. Args &&...args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
  1086. : _status(status::have_error)
  1087. , _error(il, static_cast<Args &&>(args)...)
  1088. {
  1089. _set_error_is_errno(*this);
  1090. }
  1091. struct nonvoid_converting_constructor_tag
  1092. {
  1093. };
  1094. template <class U, class V>
  1095. static constexpr bool enable_nonvoid_converting_constructor =
  1096. !(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value) //
  1097. && detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
  1098. BOOST_OUTCOME_TEMPLATE(class U, class V)
  1099. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  1100. constexpr explicit value_storage_nontrivial(const value_storage_trivial<U, V> &o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
  1101. detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
  1102. : value_storage_nontrivial(o._status.have_value() ?
  1103. value_storage_nontrivial(in_place_type<value_type>, o._value) :
  1104. (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
  1105. {
  1106. _status = o._status;
  1107. }
  1108. BOOST_OUTCOME_TEMPLATE(class U, class V)
  1109. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  1110. constexpr explicit value_storage_nontrivial(value_storage_trivial<U, V> &&o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
  1111. detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
  1112. : value_storage_nontrivial(
  1113. o._status.have_value() ?
  1114. value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
  1115. (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
  1116. {
  1117. _status = o._status;
  1118. }
  1119. BOOST_OUTCOME_TEMPLATE(class U, class V)
  1120. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  1121. constexpr explicit value_storage_nontrivial(const value_storage_nontrivial<U, V> &o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
  1122. detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
  1123. : value_storage_nontrivial(o._status.have_value() ?
  1124. value_storage_nontrivial(in_place_type<value_type>, o._value) :
  1125. (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
  1126. {
  1127. _status = o._status;
  1128. }
  1129. BOOST_OUTCOME_TEMPLATE(class U, class V)
  1130. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
  1131. constexpr explicit value_storage_nontrivial(value_storage_nontrivial<U, V> &&o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
  1132. detail::is_nothrow_constructible<_value_type_, U> && detail::is_nothrow_constructible<_error_type_, V>)
  1133. : value_storage_nontrivial(
  1134. o._status.have_value() ?
  1135. value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
  1136. (o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
  1137. {
  1138. _status = o._status;
  1139. }
  1140. struct void_value_converting_constructor_tag
  1141. {
  1142. };
  1143. template <class V>
  1144. static constexpr bool enable_void_value_converting_constructor =
  1145. std::is_default_constructible<value_type>::value && detail::is_constructible<error_type, V>;
  1146. BOOST_OUTCOME_TEMPLATE(class V)
  1147. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
  1148. constexpr explicit value_storage_nontrivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
  1149. std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
  1150. {
  1151. if(o._status.have_value())
  1152. {
  1153. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(); // NOLINT
  1154. }
  1155. else if(o._status.have_error())
  1156. {
  1157. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(o._error); // NOLINT
  1158. }
  1159. _status = o._status;
  1160. }
  1161. BOOST_OUTCOME_TEMPLATE(class V)
  1162. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
  1163. constexpr explicit value_storage_nontrivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
  1164. std::is_nothrow_default_constructible<_value_type_>::value && detail::is_nothrow_constructible<_error_type_, V>)
  1165. {
  1166. if(o._status.have_value())
  1167. {
  1168. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(); // NOLINT
  1169. }
  1170. else if(o._status.have_error())
  1171. {
  1172. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
  1173. }
  1174. _status = o._status;
  1175. o._status.set_have_moved_from(true);
  1176. }
  1177. struct void_error_converting_constructor_tag
  1178. {
  1179. };
  1180. template <class U>
  1181. static constexpr bool enable_void_error_converting_constructor =
  1182. std::is_default_constructible<error_type>::value && detail::is_constructible<value_type, U>;
  1183. BOOST_OUTCOME_TEMPLATE(class U)
  1184. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
  1185. constexpr explicit value_storage_nontrivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
  1186. detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
  1187. {
  1188. if(o._status.have_value())
  1189. {
  1190. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(o._value); // NOLINT
  1191. }
  1192. else if(o._status.have_error())
  1193. {
  1194. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(); // NOLINT
  1195. }
  1196. _status = o._status;
  1197. }
  1198. BOOST_OUTCOME_TEMPLATE(class U)
  1199. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
  1200. constexpr explicit value_storage_nontrivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
  1201. detail::is_nothrow_constructible<_value_type_, U> && std::is_nothrow_default_constructible<_error_type_>::value)
  1202. {
  1203. if(o._status.have_value())
  1204. {
  1205. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
  1206. }
  1207. else if(o._status.have_error())
  1208. {
  1209. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(); // NOLINT
  1210. }
  1211. _status = o._status;
  1212. o._status.set_have_moved_from(true);
  1213. }
  1214. #if __cplusplus >= 202000L || _HAS_CXX20
  1215. constexpr
  1216. #endif
  1217. ~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<_value_type_>::value && std::is_nothrow_destructible<_error_type_>::value)
  1218. {
  1219. if(this->_status.have_value())
  1220. {
  1221. if(!trait::is_move_bitcopying<value_type>::value || !this->_status.have_moved_from())
  1222. {
  1223. this->_value.~_value_type_(); // NOLINT
  1224. }
  1225. this->_status.set_have_value(false);
  1226. }
  1227. else if(this->_status.have_error())
  1228. {
  1229. if(!trait::is_move_bitcopying<error_type>::value || !this->_status.have_moved_from())
  1230. {
  1231. this->_error.~_error_type_(); // NOLINT
  1232. }
  1233. this->_status.set_have_error(false);
  1234. }
  1235. }
  1236. #if __cplusplus >= 202000L || _HAS_CXX20
  1237. constexpr
  1238. #endif
  1239. void
  1240. swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<_value_type_>::value && detail::is_nothrow_swappable<_error_type_>::value)
  1241. {
  1242. using std::swap;
  1243. // empty/empty
  1244. if(!_status.have_value() && !o._status.have_value() && !_status.have_error() && !o._status.have_error())
  1245. {
  1246. swap(_status, o._status);
  1247. return;
  1248. }
  1249. // value/value
  1250. if(_status.have_value() && o._status.have_value())
  1251. {
  1252. struct some_type
  1253. {
  1254. status_bitfield_type &a, &b;
  1255. bool all_good{false};
  1256. ~some_type()
  1257. {
  1258. if(!this->all_good)
  1259. {
  1260. // We lost one of the values
  1261. this->a.set_have_lost_consistency(true);
  1262. this->b.set_have_lost_consistency(true);
  1263. }
  1264. }
  1265. } some_type_value{_status, o._status};
  1266. strong_swap(some_type_value.all_good, _value, o._value);
  1267. swap(_status, o._status);
  1268. return;
  1269. }
  1270. // error/error
  1271. if(_status.have_error() && o._status.have_error())
  1272. {
  1273. struct some_type
  1274. {
  1275. status_bitfield_type &a, &b;
  1276. bool all_good{false};
  1277. ~some_type()
  1278. {
  1279. if(!this->all_good)
  1280. {
  1281. // We lost one of the values
  1282. this->a.set_have_lost_consistency(true);
  1283. this->b.set_have_lost_consistency(true);
  1284. }
  1285. }
  1286. } some_type_value{_status, o._status};
  1287. strong_swap(some_type_value.all_good, _error, o._error);
  1288. swap(_status, o._status);
  1289. return;
  1290. }
  1291. // Could be value/empty, error/empty, etc
  1292. if(_status.have_value() && !o._status.have_error())
  1293. {
  1294. // Move construct me into other
  1295. new(BOOST_OUTCOME_ADDRESS_OF(o._value)) _value_type_(static_cast<_value_type_ &&>(_value)); // NOLINT
  1296. if(!trait::is_move_bitcopying<value_type>::value)
  1297. {
  1298. this->_value.~value_type(); // NOLINT
  1299. }
  1300. swap(_status, o._status);
  1301. return;
  1302. }
  1303. if(o._status.have_value() && !_status.have_error())
  1304. {
  1305. // Move construct other into me
  1306. new(BOOST_OUTCOME_ADDRESS_OF(_value)) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
  1307. if(!trait::is_move_bitcopying<value_type>::value)
  1308. {
  1309. o._value.~value_type(); // NOLINT
  1310. }
  1311. swap(_status, o._status);
  1312. return;
  1313. }
  1314. if(_status.have_error() && !o._status.have_value())
  1315. {
  1316. // Move construct me into other
  1317. new(BOOST_OUTCOME_ADDRESS_OF(o._error)) _error_type_(static_cast<_error_type_ &&>(_error)); // NOLINT
  1318. if(!trait::is_move_bitcopying<error_type>::value)
  1319. {
  1320. this->_error.~error_type(); // NOLINT
  1321. }
  1322. swap(_status, o._status);
  1323. return;
  1324. }
  1325. if(o._status.have_error() && !_status.have_value())
  1326. {
  1327. // Move construct other into me
  1328. new(BOOST_OUTCOME_ADDRESS_OF(_error)) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
  1329. if(!trait::is_move_bitcopying<error_type>::value)
  1330. {
  1331. o._error.~error_type(); // NOLINT
  1332. }
  1333. swap(_status, o._status);
  1334. return;
  1335. }
  1336. // It can now only be value/error, or error/value
  1337. struct some_type
  1338. {
  1339. status_bitfield_type &a, &b;
  1340. _value_type_ *value, *o_value;
  1341. _error_type_ *error, *o_error;
  1342. bool all_good{true};
  1343. ~some_type()
  1344. {
  1345. if(!this->all_good)
  1346. {
  1347. // We lost one of the values
  1348. this->a.set_have_lost_consistency(true);
  1349. this->b.set_have_lost_consistency(true);
  1350. }
  1351. }
  1352. } 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)};
  1353. if(_status.have_value() && o._status.have_error())
  1354. {
  1355. strong_placement(some_type_value.all_good, some_type_value.o_value, some_type_value.value, [&some_type_value] { //
  1356. strong_placement(some_type_value.all_good, some_type_value.error, some_type_value.o_error, [&some_type_value] { //
  1357. swap(some_type_value.a, some_type_value.b); //
  1358. });
  1359. });
  1360. return;
  1361. }
  1362. if(_status.have_error() && o._status.have_value())
  1363. {
  1364. strong_placement(some_type_value.all_good, some_type_value.o_error, some_type_value.error, [&some_type_value] { //
  1365. strong_placement(some_type_value.all_good, some_type_value.value, some_type_value.o_value, [&some_type_value] { //
  1366. swap(some_type_value.a, some_type_value.b); //
  1367. });
  1368. });
  1369. return;
  1370. }
  1371. // Should never reach here
  1372. make_ub(_value);
  1373. }
  1374. };
  1375. template <class Base> struct value_storage_delete_copy_constructor : Base // NOLINT
  1376. {
  1377. using Base::Base;
  1378. using value_type = typename Base::value_type;
  1379. using error_type = typename Base::error_type;
  1380. value_storage_delete_copy_constructor() = default;
  1381. value_storage_delete_copy_constructor(const value_storage_delete_copy_constructor &) = delete;
  1382. value_storage_delete_copy_constructor(value_storage_delete_copy_constructor &&) = default; // NOLINT
  1383. value_storage_delete_copy_constructor &operator=(const value_storage_delete_copy_constructor &o) = default;
  1384. value_storage_delete_copy_constructor &operator=(value_storage_delete_copy_constructor &&o) = default; // NOLINT
  1385. ~value_storage_delete_copy_constructor() = default;
  1386. };
  1387. template <class Base> struct value_storage_delete_copy_assignment : Base // NOLINT
  1388. {
  1389. using Base::Base;
  1390. using value_type = typename Base::value_type;
  1391. using error_type = typename Base::error_type;
  1392. value_storage_delete_copy_assignment() = default;
  1393. value_storage_delete_copy_assignment(const value_storage_delete_copy_assignment &) = default;
  1394. value_storage_delete_copy_assignment(value_storage_delete_copy_assignment &&) = default; // NOLINT
  1395. value_storage_delete_copy_assignment &operator=(const value_storage_delete_copy_assignment &o) = delete;
  1396. value_storage_delete_copy_assignment &operator=(value_storage_delete_copy_assignment &&o) = default; // NOLINT
  1397. ~value_storage_delete_copy_assignment() = default;
  1398. };
  1399. template <class Base> struct value_storage_delete_move_assignment : Base // NOLINT
  1400. {
  1401. using Base::Base;
  1402. using value_type = typename Base::value_type;
  1403. using error_type = typename Base::error_type;
  1404. value_storage_delete_move_assignment() = default;
  1405. value_storage_delete_move_assignment(const value_storage_delete_move_assignment &) = default;
  1406. value_storage_delete_move_assignment(value_storage_delete_move_assignment &&) = default; // NOLINT
  1407. value_storage_delete_move_assignment &operator=(const value_storage_delete_move_assignment &o) = default;
  1408. value_storage_delete_move_assignment &operator=(value_storage_delete_move_assignment &&o) = delete;
  1409. ~value_storage_delete_move_assignment() = default;
  1410. };
  1411. template <class Base> struct value_storage_delete_move_constructor : Base // NOLINT
  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_move_constructor() = default;
  1417. value_storage_delete_move_constructor(const value_storage_delete_move_constructor &) = default;
  1418. value_storage_delete_move_constructor(value_storage_delete_move_constructor &&) = delete;
  1419. value_storage_delete_move_constructor &operator=(const value_storage_delete_move_constructor &o) = default;
  1420. value_storage_delete_move_constructor &operator=(value_storage_delete_move_constructor &&o) = default;
  1421. ~value_storage_delete_move_constructor() = default;
  1422. };
  1423. template <class Base> struct value_storage_nontrivial_move_assignment : Base // NOLINT
  1424. {
  1425. using Base::Base;
  1426. using value_type = typename Base::value_type;
  1427. using error_type = typename Base::error_type;
  1428. value_storage_nontrivial_move_assignment() = default;
  1429. value_storage_nontrivial_move_assignment(const value_storage_nontrivial_move_assignment &) = default;
  1430. value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default; // NOLINT
  1431. value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
  1432. ~value_storage_nontrivial_move_assignment() = default;
  1433. #if __cplusplus >= 202000L || _HAS_CXX20
  1434. constexpr
  1435. #endif
  1436. value_storage_nontrivial_move_assignment &
  1437. operator=(value_storage_nontrivial_move_assignment &&o) noexcept(std::is_nothrow_move_assignable<value_type>::value &&
  1438. std::is_nothrow_move_assignable<error_type>::value &&
  1439. noexcept(move_assign_to_empty<value_type>(static_cast<value_type *>(nullptr),
  1440. static_cast<value_type *>(nullptr))) &&
  1441. noexcept(move_assign_to_empty<error_type>(static_cast<error_type *>(nullptr),
  1442. static_cast<error_type *>(nullptr)))) // NOLINT
  1443. {
  1444. using _value_type_ = typename Base::_value_type_;
  1445. using _error_type_ = typename Base::_error_type_;
  1446. if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
  1447. {
  1448. this->_status = o._status;
  1449. o._status.set_have_moved_from(true);
  1450. return *this;
  1451. }
  1452. if(this->_status.have_value() && o._status.have_value())
  1453. {
  1454. this->_value = static_cast<_value_type_ &&>(o._value); // NOLINT
  1455. this->_status = o._status;
  1456. o._status.set_have_moved_from(true);
  1457. return *this;
  1458. }
  1459. if(this->_status.have_error() && o._status.have_error())
  1460. {
  1461. this->_error = static_cast<_error_type_ &&>(o._error); // NOLINT
  1462. this->_status = o._status;
  1463. o._status.set_have_moved_from(true);
  1464. return *this;
  1465. }
  1466. if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
  1467. {
  1468. if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
  1469. {
  1470. this->_value.~_value_type_(); // NOLINT
  1471. }
  1472. this->_status = o._status;
  1473. o._status.set_have_moved_from(true);
  1474. return *this;
  1475. }
  1476. if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
  1477. {
  1478. move_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
  1479. this->_status = o._status;
  1480. o._status.set_have_moved_from(true);
  1481. return *this;
  1482. }
  1483. if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
  1484. {
  1485. if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
  1486. {
  1487. this->_error.~_error_type_(); // NOLINT
  1488. }
  1489. this->_status = o._status;
  1490. o._status.set_have_moved_from(true);
  1491. return *this;
  1492. }
  1493. if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
  1494. {
  1495. move_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
  1496. this->_status = o._status;
  1497. o._status.set_have_moved_from(true);
  1498. return *this;
  1499. }
  1500. if(this->_status.have_value() && o._status.have_error())
  1501. {
  1502. if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
  1503. {
  1504. this->_value.~_value_type_(); // NOLINT
  1505. }
  1506. move_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
  1507. this->_status = o._status;
  1508. o._status.set_have_moved_from(true);
  1509. return *this;
  1510. }
  1511. if(this->_status.have_error() && o._status.have_value())
  1512. {
  1513. if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
  1514. {
  1515. this->_error.~_error_type_(); // NOLINT
  1516. }
  1517. move_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
  1518. this->_status = o._status;
  1519. o._status.set_have_moved_from(true);
  1520. return *this;
  1521. }
  1522. // Should never reach here
  1523. make_ub(this->_value);
  1524. }
  1525. };
  1526. template <class Base> struct value_storage_nontrivial_copy_assignment : Base // NOLINT
  1527. {
  1528. using Base::Base;
  1529. using value_type = typename Base::value_type;
  1530. using error_type = typename Base::error_type;
  1531. value_storage_nontrivial_copy_assignment() = default;
  1532. value_storage_nontrivial_copy_assignment(const value_storage_nontrivial_copy_assignment &) = default;
  1533. value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default; // NOLINT
  1534. value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default; // NOLINT
  1535. ~value_storage_nontrivial_copy_assignment() = default;
  1536. #if __cplusplus >= 202000L || _HAS_CXX20
  1537. constexpr
  1538. #endif
  1539. value_storage_nontrivial_copy_assignment &
  1540. operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(
  1541. std::is_nothrow_copy_assignable<value_type>::value && std::is_nothrow_copy_assignable<error_type>::value &&
  1542. noexcept(copy_assign_to_empty<value_type>(static_cast<value_type *>(nullptr), static_cast<value_type *>(nullptr))) &&
  1543. noexcept(copy_assign_to_empty<error_type>(static_cast<error_type *>(nullptr), static_cast<error_type *>(nullptr))))
  1544. {
  1545. using _value_type_ = typename Base::_value_type_;
  1546. using _error_type_ = typename Base::_error_type_;
  1547. if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
  1548. {
  1549. this->_status = o._status;
  1550. return *this;
  1551. }
  1552. if(this->_status.have_value() && o._status.have_value())
  1553. {
  1554. this->_value = o._value; // NOLINT
  1555. this->_status = o._status;
  1556. return *this;
  1557. }
  1558. if(this->_status.have_error() && o._status.have_error())
  1559. {
  1560. this->_error = o._error; // NOLINT
  1561. this->_status = o._status;
  1562. return *this;
  1563. }
  1564. if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
  1565. {
  1566. if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
  1567. {
  1568. this->_value.~_value_type_(); // NOLINT
  1569. }
  1570. this->_status = o._status;
  1571. return *this;
  1572. }
  1573. if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
  1574. {
  1575. copy_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
  1576. this->_status = o._status;
  1577. return *this;
  1578. }
  1579. if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
  1580. {
  1581. if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
  1582. {
  1583. this->_error.~_error_type_(); // NOLINT
  1584. }
  1585. this->_status = o._status;
  1586. return *this;
  1587. }
  1588. if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
  1589. {
  1590. copy_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
  1591. this->_status = o._status;
  1592. return *this;
  1593. }
  1594. if(this->_status.have_value() && o._status.have_error())
  1595. {
  1596. if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
  1597. {
  1598. this->_value.~_value_type_(); // NOLINT
  1599. }
  1600. copy_assign_to_empty<_error_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_error), BOOST_OUTCOME_ADDRESS_OF(o._error));
  1601. this->_status = o._status;
  1602. return *this;
  1603. }
  1604. if(this->_status.have_error() && o._status.have_value())
  1605. {
  1606. if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
  1607. {
  1608. this->_error.~_error_type_(); // NOLINT
  1609. }
  1610. copy_assign_to_empty<_value_type_>(BOOST_OUTCOME_ADDRESS_OF(this->_value), BOOST_OUTCOME_ADDRESS_OF(o._value));
  1611. this->_status = o._status;
  1612. return *this;
  1613. }
  1614. // Should never reach here
  1615. make_ub(this->_value);
  1616. }
  1617. };
  1618. #ifdef _MSC_VER
  1619. #pragma warning(pop)
  1620. #endif
  1621. // is_trivially_copyable is true even if type is not copyable, so handle that here
  1622. template <class T> struct is_storage_trivial
  1623. {
  1624. static constexpr bool value = std::is_void<T>::value || (std::is_trivially_copy_constructible<T>::value && std::is_trivially_copyable<T>::value);
  1625. };
  1626. // work around libstdc++ 7 bug
  1627. template <> struct is_storage_trivial<void>
  1628. {
  1629. static constexpr bool value = true;
  1630. };
  1631. template <> struct is_storage_trivial<const void>
  1632. {
  1633. static constexpr bool value = true;
  1634. };
  1635. // Ability to do copy assigns needs more than just copy assignment
  1636. template <class T> struct is_copy_assignable
  1637. {
  1638. static constexpr bool value = std::is_copy_assignable<T>::value && (std::is_copy_constructible<T>::value || std::is_default_constructible<T>::value);
  1639. };
  1640. // Ability to do move assigns needs more than just move assignment
  1641. template <class T> struct is_move_assignable
  1642. {
  1643. static constexpr bool value = std::is_move_assignable<T>::value && (std::is_move_constructible<T>::value || std::is_default_constructible<T>::value);
  1644. };
  1645. template <class T, class E>
  1646. using value_storage_select_trivality =
  1647. std::conditional_t<is_storage_trivial<T>::value && is_storage_trivial<E>::value, value_storage_trivial<T, E>, value_storage_nontrivial<T, E>>;
  1648. template <class T, class E>
  1649. using value_storage_select_move_constructor =
  1650. std::conditional_t<std::is_move_constructible<devoid<T>>::value && std::is_move_constructible<devoid<E>>::value, value_storage_select_trivality<T, E>,
  1651. value_storage_delete_move_constructor<value_storage_select_trivality<T, E>>>;
  1652. template <class T, class E>
  1653. using value_storage_select_copy_constructor =
  1654. std::conditional_t<std::is_copy_constructible<devoid<T>>::value && std::is_copy_constructible<devoid<E>>::value, value_storage_select_move_constructor<T, E>,
  1655. value_storage_delete_copy_constructor<value_storage_select_move_constructor<T, E>>>;
  1656. template <class T, class E>
  1657. using value_storage_select_move_assignment =
  1658. std::conditional_t<std::is_trivially_move_assignable<devoid<T>>::value && std::is_trivially_move_assignable<devoid<E>>::value,
  1659. value_storage_select_copy_constructor<T, E>,
  1660. std::conditional_t<is_move_assignable<devoid<T>>::value && is_move_assignable<devoid<E>>::value,
  1661. value_storage_nontrivial_move_assignment<value_storage_select_copy_constructor<T, E>>,
  1662. value_storage_delete_move_assignment<value_storage_select_copy_constructor<T, E>>>>;
  1663. template <class T, class E>
  1664. using value_storage_select_copy_assignment =
  1665. std::conditional_t<std::is_trivially_copy_assignable<devoid<T>>::value && std::is_trivially_copy_assignable<devoid<E>>::value,
  1666. value_storage_select_move_assignment<T, E>,
  1667. std::conditional_t<is_copy_assignable<devoid<T>>::value && is_copy_assignable<devoid<E>>::value,
  1668. value_storage_nontrivial_copy_assignment<value_storage_select_move_assignment<T, E>>,
  1669. value_storage_delete_copy_assignment<value_storage_select_move_assignment<T, E>>>>;
  1670. template <class T, class E> using value_storage_select_impl = value_storage_select_copy_assignment<T, E>;
  1671. #ifndef NDEBUG
  1672. // Check is trivial in all ways except default constructibility
  1673. // static_assert(std::is_trivial<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivial!");
  1674. // static_assert(std::is_trivially_default_constructible<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not
  1675. // trivially default constructible!");
  1676. static_assert(std::is_trivially_copyable<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivially copyable!");
  1677. static_assert(std::is_trivially_assignable<value_storage_select_impl<int, long>, value_storage_select_impl<int, long>>::value,
  1678. "value_storage_select_impl<int, long> is not trivially assignable!");
  1679. static_assert(std::is_trivially_destructible<value_storage_select_impl<int, long>>::value,
  1680. "value_storage_select_impl<int, long> is not trivially destructible!");
  1681. static_assert(std::is_trivially_copy_constructible<value_storage_select_impl<int, long>>::value,
  1682. "value_storage_select_impl<int, long> is not trivially copy constructible!");
  1683. static_assert(std::is_trivially_move_constructible<value_storage_select_impl<int, long>>::value,
  1684. "value_storage_select_impl<int, long> is not trivially move constructible!");
  1685. static_assert(std::is_trivially_copy_assignable<value_storage_select_impl<int, long>>::value,
  1686. "value_storage_select_impl<int, long> is not trivially copy assignable!");
  1687. static_assert(std::is_trivially_move_assignable<value_storage_select_impl<int, long>>::value,
  1688. "value_storage_select_impl<int, long> is not trivially move assignable!");
  1689. // Also check is standard layout
  1690. 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!");
  1691. #endif
  1692. } // namespace detail
  1693. BOOST_OUTCOME_V2_NAMESPACE_END
  1694. #endif