value_storage.hpp 69 KB

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