basic_outcome.hpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. /* A less simple result type
  2. (C) 2017-2025 Niall Douglas <http://www.nedproductions.biz/> (20 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_BASIC_OUTCOME_HPP
  26. #define BOOST_OUTCOME_BASIC_OUTCOME_HPP
  27. #include "config.hpp"
  28. #include "basic_result.hpp"
  29. #include "detail/basic_outcome_exception_observers.hpp"
  30. #include "detail/basic_outcome_failure_observers.hpp"
  31. #ifdef __clang__
  32. #pragma clang diagnostic push
  33. #pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
  34. #endif
  35. #if defined(_MSC_VER) && !defined(__clang__)
  36. #pragma warning(push)
  37. #pragma warning(disable : 6287) // redundant code
  38. #endif
  39. BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
  40. template <class R, class S, class P, class NoValuePolicy> //
  41. class basic_outcome;
  42. namespace detail
  43. {
  44. // May be reused by basic_outcome subclasses to save load on the compiler
  45. template <class value_type, class error_type, class exception_type> struct outcome_predicates
  46. {
  47. using result = result_predicates<value_type, error_type>;
  48. // Predicate for the implicit constructors to be available
  49. static constexpr bool implicit_constructors_enabled = //
  50. result::implicit_constructors_enabled //
  51. && !detail::is_implicitly_constructible<value_type, exception_type> //
  52. && !detail::is_implicitly_constructible<error_type, exception_type> //
  53. && !detail::is_implicitly_constructible<exception_type, value_type> //
  54. && !detail::is_implicitly_constructible<exception_type, error_type>;
  55. // Predicate for the value converting constructor to be available.
  56. template <class T>
  57. static constexpr bool enable_value_converting_constructor = //
  58. implicit_constructors_enabled //
  59. && result::template enable_value_converting_constructor<T> //
  60. && !detail::is_implicitly_constructible<exception_type, T>; // deliberately less tolerant of ambiguity than result's edition
  61. // Predicate for the error converting constructor to be available.
  62. template <class T>
  63. static constexpr bool enable_error_converting_constructor = //
  64. implicit_constructors_enabled //
  65. && result::template enable_error_converting_constructor<T> //
  66. && !detail::is_implicitly_constructible<exception_type, T>; // deliberately less tolerant of ambiguity than result's edition
  67. // Predicate for the error condition converting constructor to be available.
  68. template <class ErrorCondEnum>
  69. static constexpr bool enable_error_condition_converting_constructor = result::template enable_error_condition_converting_constructor<ErrorCondEnum> //
  70. && !detail::is_implicitly_constructible<exception_type, ErrorCondEnum>;
  71. // Predicate for the exception converting constructor to be available.
  72. template <class T>
  73. static constexpr bool enable_exception_converting_constructor = //
  74. implicit_constructors_enabled //
  75. && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
  76. && !detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T> &&
  77. detail::is_implicitly_constructible<exception_type, T>;
  78. // Predicate for the error + exception converting constructor to be available.
  79. template <class T, class U>
  80. static constexpr bool enable_error_exception_converting_constructor = //
  81. implicit_constructors_enabled //
  82. && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
  83. && !detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T> //
  84. && !detail::is_implicitly_constructible<value_type, U> && detail::is_implicitly_constructible<exception_type, U>;
  85. // Predicate for the converting copy constructor from a compatible outcome to be available.
  86. template <class T, class U, class V, class W>
  87. static constexpr bool enable_compatible_conversion = //
  88. (std::is_void<T>::value ||
  89. detail::is_explicitly_constructible<value_type, typename basic_outcome<T, U, V, W>::value_type>) // if our value types are constructible
  90. &&(std::is_void<U>::value ||
  91. detail::is_explicitly_constructible<error_type, typename basic_outcome<T, U, V, W>::error_type>) // if our error types are constructible
  92. &&(std::is_void<V>::value ||
  93. detail::is_explicitly_constructible<exception_type, typename basic_outcome<T, U, V, W>::exception_type>) // if our exception types are constructible
  94. ;
  95. // Predicate for the converting constructor from a make_error_code() of the input to be available.
  96. template <class T, class U, class V, class W>
  97. static constexpr bool enable_make_error_code_compatible_conversion = //
  98. trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
  99. && !enable_compatible_conversion<T, U, V, W> // and the normal compatible conversion is not available
  100. && (std::is_void<T>::value ||
  101. detail::is_explicitly_constructible<value_type, typename basic_outcome<T, U, V, W>::value_type>) // and if our value types are constructible
  102. &&detail::is_explicitly_constructible<error_type,
  103. typename trait::is_error_code_available<U>::type> // and our error type is constructible from a make_error_code()
  104. && (std::is_void<V>::value ||
  105. detail::is_explicitly_constructible<exception_type, typename basic_outcome<T, U, V, W>::exception_type>); // and our exception types are constructible
  106. // Predicate for the implicit converting inplace constructor from a compatible input to be available.
  107. struct disable_inplace_value_error_exception_constructor;
  108. template <class... Args>
  109. using choose_inplace_value_error_exception_constructor = std::conditional_t< //
  110. ((static_cast<int>(detail::is_constructible<value_type, Args...>) + static_cast<int>(detail::is_constructible<error_type, Args...>) +
  111. static_cast<int>(detail::is_constructible<exception_type, Args...>)) > 1), //
  112. disable_inplace_value_error_exception_constructor, //
  113. std::conditional_t< //
  114. detail::is_constructible<value_type, Args...>, //
  115. value_type, //
  116. std::conditional_t< //
  117. detail::is_constructible<error_type, Args...>, //
  118. error_type, //
  119. std::conditional_t< //
  120. detail::is_constructible<exception_type, Args...>, //
  121. exception_type, //
  122. disable_inplace_value_error_exception_constructor>>>>;
  123. template <class... Args>
  124. static constexpr bool enable_inplace_value_error_exception_constructor = //
  125. implicit_constructors_enabled &&
  126. !std::is_same<choose_inplace_value_error_exception_constructor<Args...>, disable_inplace_value_error_exception_constructor>::value;
  127. };
  128. // Select whether to use basic_outcome_failure_observers or not
  129. template <class Base, class R, class S, class P, class NoValuePolicy>
  130. using select_basic_outcome_failure_observers = //
  131. std::conditional_t<trait::is_error_code_available<S>::value && trait::is_exception_ptr_available<P>::value,
  132. basic_outcome_failure_observers<Base, R, S, P, NoValuePolicy>, Base>;
  133. template <class T, class U, class V> constexpr inline const V &extract_exception_from_failure(const failure_type<U, V> &v)
  134. {
  135. return v.exception();
  136. }
  137. template <class T, class U, class V> constexpr inline V &&extract_exception_from_failure(failure_type<U, V> &&v)
  138. {
  139. return static_cast<failure_type<U, V> &&>(v).exception();
  140. }
  141. template <class T, class U> constexpr inline const U &extract_exception_from_failure(const failure_type<U, void> &v)
  142. {
  143. return v.error();
  144. }
  145. template <class T, class U> constexpr inline U &&extract_exception_from_failure(failure_type<U, void> &&v)
  146. {
  147. return static_cast<failure_type<U, void> &&>(v).error();
  148. }
  149. template <class T> struct is_basic_outcome
  150. {
  151. static constexpr bool value = false;
  152. };
  153. template <class R, class S, class T, class N> struct is_basic_outcome<basic_outcome<R, S, T, N>>
  154. {
  155. static constexpr bool value = true;
  156. };
  157. } // namespace detail
  158. /*! AWAITING HUGO JSON CONVERSION TOOL
  159. type alias template <class T> is_basic_outcome. Potential doc page: `is_basic_outcome<T>`
  160. */
  161. template <class T> using is_basic_outcome = detail::is_basic_outcome<std::decay_t<T>>;
  162. /*! AWAITING HUGO JSON CONVERSION TOOL
  163. SIGNATURE NOT RECOGNISED
  164. */
  165. template <class T> static constexpr bool is_basic_outcome_v = detail::is_basic_outcome<std::decay_t<T>>::value;
  166. namespace concepts
  167. {
  168. #if defined(__cpp_concepts)
  169. /* The `basic_outcome` concept.
  170. \requires That `U` matches a `basic_outcome`.
  171. */
  172. template <class U>
  173. concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL basic_outcome =
  174. BOOST_OUTCOME_V2_NAMESPACE::is_basic_outcome<U>::value ||
  175. (requires(U v) {
  176. BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>(v);
  177. } && //
  178. detail::convertible<
  179. U, BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>> && //
  180. detail::base_of<
  181. BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>, U>);
  182. #else
  183. namespace detail
  184. {
  185. inline no_match match_basic_outcome(...);
  186. template <class R, class S, class P, class NVP, class T, //
  187. typename = typename T::value_type, //
  188. typename = typename T::error_type, //
  189. typename = typename T::exception_type, //
  190. typename = typename T::no_value_policy_type, //
  191. typename std::enable_if_t<std::is_convertible<T, BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP>>::value && //
  192. std::is_base_of<BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP>, T>::value,
  193. bool> = true>
  194. inline BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP> match_basic_outcome(BOOST_OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP> &&, T &&);
  195. template <class U>
  196. static constexpr bool basic_outcome =
  197. BOOST_OUTCOME_V2_NAMESPACE::is_basic_outcome<U>::value ||
  198. !std::is_same<no_match, decltype(match_basic_outcome(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>(),
  199. std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
  200. } // namespace detail
  201. /* The `basic_outcome` concept.
  202. \requires That `U` matches a `basic_outcome`.
  203. */
  204. template <class U> static constexpr bool basic_outcome = detail::basic_outcome<U>;
  205. #endif
  206. } // namespace concepts
  207. namespace hooks
  208. {
  209. /*! AWAITING HUGO JSON CONVERSION TOOL
  210. SIGNATURE NOT RECOGNISED
  211. */
  212. template <class R, class S, class P, class NoValuePolicy, class U>
  213. constexpr inline void override_outcome_exception(basic_outcome<R, S, P, NoValuePolicy> *o, U &&v) noexcept;
  214. } // namespace hooks
  215. /*! AWAITING HUGO JSON CONVERSION TOOL
  216. type definition template <class R, class S, class P, class NoValuePolicy> basic_outcome. Potential doc page: `basic_outcome<T, EC, EP, NoValuePolicy>`
  217. */
  218. template <class R, class S, class P, class NoValuePolicy> //
  219. class BOOST_OUTCOME_NODISCARD basic_outcome
  220. #if defined(BOOST_OUTCOME_DOXYGEN_IS_IN_THE_HOUSE) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
  221. : public detail::basic_outcome_failure_observers<detail::basic_result_final<R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>,
  222. public detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>,
  223. public detail::basic_result_final<R, S, NoValuePolicy>
  224. #else
  225. : public detail::select_basic_outcome_failure_observers<
  226. detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>
  227. #endif
  228. {
  229. static_assert(trait::type_can_be_used_in_basic_result<P>, "The exception_type cannot be used");
  230. static_assert(std::is_void<P>::value || std::is_default_constructible<P>::value, "exception_type must be void or default constructible");
  231. using base = detail::select_basic_outcome_failure_observers<
  232. detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>;
  233. friend struct policy::base;
  234. template <class T, class U, class V, class W> //
  235. friend class basic_outcome;
  236. template <class T, class U, class V, class W, class X>
  237. friend constexpr inline void hooks::override_outcome_exception(basic_outcome<T, U, V, W> *o, X &&v) noexcept; // NOLINT
  238. struct implicit_constructors_disabled_tag
  239. {
  240. };
  241. struct value_converting_constructor_tag
  242. {
  243. };
  244. struct error_converting_constructor_tag
  245. {
  246. };
  247. struct error_condition_converting_constructor_tag
  248. {
  249. };
  250. struct exception_converting_constructor_tag
  251. {
  252. };
  253. struct error_exception_converting_constructor_tag
  254. {
  255. };
  256. struct explicit_valueorerror_converting_constructor_tag
  257. {
  258. };
  259. struct explicit_compatible_copy_conversion_tag
  260. {
  261. };
  262. struct explicit_compatible_move_conversion_tag
  263. {
  264. };
  265. struct explicit_make_error_code_compatible_copy_conversion_tag
  266. {
  267. };
  268. struct explicit_make_error_code_compatible_move_conversion_tag
  269. {
  270. };
  271. struct error_failure_tag
  272. {
  273. };
  274. struct exception_failure_tag
  275. {
  276. };
  277. struct disable_in_place_value_type
  278. {
  279. };
  280. struct disable_in_place_error_type
  281. {
  282. };
  283. struct disable_in_place_exception_type
  284. {
  285. };
  286. public:
  287. using value_type = R;
  288. using error_type = S;
  289. using exception_type = P;
  290. using no_value_policy_type = NoValuePolicy;
  291. template <class T, class U = S, class V = P, class W = NoValuePolicy> using rebind = basic_outcome<T, U, V, W>;
  292. protected:
  293. // Requirement predicates for outcome.
  294. struct predicate
  295. {
  296. using base = detail::outcome_predicates<value_type, error_type, exception_type>;
  297. // Predicate for any constructors to be available at all
  298. static constexpr bool constructors_enabled =
  299. (!std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value || (std::is_void<value_type>::value && std::is_void<error_type>::value)) //
  300. && (!std::is_same<std::decay_t<value_type>, std::decay_t<exception_type>>::value ||
  301. (std::is_void<value_type>::value && std::is_void<exception_type>::value)) //
  302. && (!std::is_same<std::decay_t<error_type>, std::decay_t<exception_type>>::value ||
  303. (std::is_void<error_type>::value && std::is_void<exception_type>::value)) //
  304. ;
  305. // Predicate for implicit constructors to be available at all
  306. static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
  307. // Predicate for the value converting constructor to be available.
  308. template <class T>
  309. static constexpr bool enable_value_converting_constructor = //
  310. constructors_enabled //
  311. && !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
  312. && base::template enable_value_converting_constructor<T>;
  313. // Predicate for the error converting constructor to be available.
  314. template <class T>
  315. static constexpr bool enable_error_converting_constructor = //
  316. constructors_enabled //
  317. && !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
  318. && base::template enable_error_converting_constructor<T>;
  319. // Predicate for the error condition converting constructor to be available.
  320. template <class ErrorCondEnum>
  321. static constexpr bool enable_error_condition_converting_constructor = //
  322. constructors_enabled //
  323. && !std::is_same<std::decay_t<ErrorCondEnum>, basic_outcome>::value // not my type
  324. && base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
  325. // Predicate for the exception converting constructor to be available.
  326. template <class T>
  327. static constexpr bool enable_exception_converting_constructor = //
  328. constructors_enabled //
  329. && !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
  330. && base::template enable_exception_converting_constructor<T>;
  331. // Predicate for the error + exception converting constructor to be available.
  332. template <class T, class U>
  333. static constexpr bool enable_error_exception_converting_constructor = //
  334. constructors_enabled //
  335. && !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
  336. && base::template enable_error_exception_converting_constructor<T, U>;
  337. // Predicate for the converting constructor from a compatible input to be available.
  338. template <class T, class U, class V, class W>
  339. static constexpr bool enable_compatible_conversion = //
  340. constructors_enabled //
  341. && !std::is_same<basic_outcome<T, U, V, W>, basic_outcome>::value // not my type
  342. && base::template enable_compatible_conversion<T, U, V, W>;
  343. // Predicate for the converting constructor from a make_error_code() of the input to be available.
  344. template <class T, class U, class V, class W>
  345. static constexpr bool enable_make_error_code_compatible_conversion = //
  346. constructors_enabled //
  347. && !std::is_same<basic_outcome<T, U, V, W>, basic_outcome>::value // not my type
  348. && base::template enable_make_error_code_compatible_conversion<T, U, V, W>;
  349. // Predicate for the inplace construction of value to be available.
  350. template <class... Args>
  351. static constexpr bool enable_inplace_value_constructor = //
  352. constructors_enabled //
  353. && (std::is_void<value_type>::value //
  354. || detail::is_constructible<value_type, Args...>);
  355. // Predicate for the inplace construction of error to be available.
  356. template <class... Args>
  357. static constexpr bool enable_inplace_error_constructor = //
  358. constructors_enabled //
  359. && (std::is_void<error_type>::value //
  360. || detail::is_constructible<error_type, Args...>);
  361. // Predicate for the inplace construction of exception to be available.
  362. template <class... Args>
  363. static constexpr bool enable_inplace_exception_constructor = //
  364. constructors_enabled //
  365. && (std::is_void<exception_type>::value //
  366. || detail::is_constructible<exception_type, Args...>);
  367. // Predicate for the implicit converting inplace constructor to be available.
  368. template <class... Args>
  369. static constexpr bool enable_inplace_value_error_exception_constructor = //
  370. constructors_enabled //
  371. && base::template enable_inplace_value_error_exception_constructor<Args...>;
  372. template <class... Args>
  373. using choose_inplace_value_error_exception_constructor = typename base::template choose_inplace_value_error_exception_constructor<Args...>;
  374. };
  375. public:
  376. using value_type_if_enabled =
  377. std::conditional_t<std::is_same<value_type, error_type>::value || std::is_same<value_type, exception_type>::value, disable_in_place_value_type, value_type>;
  378. using error_type_if_enabled =
  379. std::conditional_t<std::is_same<error_type, value_type>::value || std::is_same<error_type, exception_type>::value, disable_in_place_error_type, error_type>;
  380. using exception_type_if_enabled = std::conditional_t<std::is_same<exception_type, value_type>::value || std::is_same<exception_type, error_type>::value,
  381. disable_in_place_exception_type, exception_type>;
  382. protected:
  383. detail::devoid<exception_type> _ptr;
  384. public:
  385. /*! AWAITING HUGO JSON CONVERSION TOOL
  386. SIGNATURE NOT RECOGNISED
  387. */
  388. BOOST_OUTCOME_TEMPLATE(class Arg, class... Args)
  389. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((!predicate::constructors_enabled && sizeof...(Args) >= 0)))
  390. basic_outcome(Arg && /*unused*/, Args &&.../*unused*/) = delete; // NOLINT basic_outcome<> with any of the same type is NOT SUPPORTED, see docs!
  391. /*! AWAITING HUGO JSON CONVERSION TOOL
  392. SIGNATURE NOT RECOGNISED
  393. */
  394. BOOST_OUTCOME_TEMPLATE(class T)
  395. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
  396. && (detail::is_implicitly_constructible<value_type, T> || detail::is_implicitly_constructible<error_type, T> ||
  397. detail::is_implicitly_constructible<exception_type, T>) )))
  398. basic_outcome(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) =
  399. delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
  400. /*! AWAITING HUGO JSON CONVERSION TOOL
  401. SIGNATURE NOT RECOGNISED
  402. */
  403. BOOST_OUTCOME_TEMPLATE(class T)
  404. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
  405. constexpr basic_outcome(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(
  406. detail::is_nothrow_constructible<value_type, T>) // NOLINT
  407. : base{in_place_type<typename base::_value_type>, static_cast<T &&>(t)}
  408. , _ptr()
  409. {
  410. no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
  411. }
  412. /*! AWAITING HUGO JSON CONVERSION TOOL
  413. SIGNATURE NOT RECOGNISED
  414. */
  415. BOOST_OUTCOME_TEMPLATE(class T)
  416. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
  417. constexpr basic_outcome(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(
  418. detail::is_nothrow_constructible<error_type, T>) // NOLINT
  419. : base{in_place_type<typename base::_error_type>, static_cast<T &&>(t)}
  420. , _ptr()
  421. {
  422. no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
  423. }
  424. /*! AWAITING HUGO JSON CONVERSION TOOL
  425. SIGNATURE NOT RECOGNISED
  426. */
  427. BOOST_OUTCOME_TEMPLATE(class ErrorCondEnum)
  428. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
  429. BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
  430. constexpr basic_outcome(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(
  431. noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
  432. : base{in_place_type<typename base::_error_type>, make_error_code(t)}
  433. {
  434. no_value_policy_type::on_outcome_construction(this, static_cast<ErrorCondEnum &&>(t));
  435. }
  436. /*! AWAITING HUGO JSON CONVERSION TOOL
  437. SIGNATURE NOT RECOGNISED
  438. */
  439. BOOST_OUTCOME_TEMPLATE(class T)
  440. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_exception_converting_constructor<T>))
  441. constexpr basic_outcome(T &&t, exception_converting_constructor_tag /*unused*/ = exception_converting_constructor_tag()) noexcept(
  442. detail::is_nothrow_constructible<exception_type, T>) // NOLINT
  443. : base()
  444. , _ptr(static_cast<T &&>(t))
  445. {
  446. this->_state._status.set_have_exception(true);
  447. no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
  448. }
  449. /*! AWAITING HUGO JSON CONVERSION TOOL
  450. SIGNATURE NOT RECOGNISED
  451. */
  452. BOOST_OUTCOME_TEMPLATE(class T, class U)
  453. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_exception_converting_constructor<T, U>))
  454. constexpr basic_outcome(T &&a, U &&b, error_exception_converting_constructor_tag /*unused*/ = error_exception_converting_constructor_tag()) noexcept(
  455. detail::is_nothrow_constructible<error_type, T> && detail::is_nothrow_constructible<exception_type, U>) // NOLINT
  456. : base{in_place_type<typename base::_error_type>, static_cast<T &&>(a)}
  457. , _ptr(static_cast<U &&>(b))
  458. {
  459. this->_state._status.set_have_exception(true);
  460. no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(a), static_cast<U &&>(b));
  461. }
  462. /*! AWAITING HUGO JSON CONVERSION TOOL
  463. SIGNATURE NOT RECOGNISED
  464. */
  465. BOOST_OUTCOME_TEMPLATE(class T)
  466. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error<basic_outcome, std::decay_t<T>>::enable_result_inputs || !concepts::basic_result<T>), //
  467. BOOST_OUTCOME_TPRED(convert::value_or_error<basic_outcome, std::decay_t<T>>::enable_outcome_inputs || !concepts::basic_outcome<T>), //
  468. BOOST_OUTCOME_TEXPR(convert::value_or_error<basic_outcome, std::decay_t<T>>{}(std::declval<T>())))
  469. constexpr explicit basic_outcome(T &&o,
  470. explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
  471. : basic_outcome{convert::value_or_error<basic_outcome, std::decay_t<T>>{}(static_cast<T &&>(o))}
  472. {
  473. }
  474. /*! AWAITING HUGO JSON CONVERSION TOOL
  475. SIGNATURE NOT RECOGNISED
  476. */
  477. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W)
  478. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V, W>))
  479. constexpr explicit basic_outcome(
  480. const basic_outcome<T, U, V, W> &o,
  481. explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  482. detail::is_nothrow_constructible<error_type, U> &&
  483. detail::is_nothrow_constructible<exception_type, V>)
  484. : base{typename base::compatible_conversion_tag(), o}
  485. , _ptr(o._ptr)
  486. {
  487. no_value_policy_type::on_outcome_copy_construction(this, o);
  488. }
  489. /*! AWAITING HUGO JSON CONVERSION TOOL
  490. SIGNATURE NOT RECOGNISED
  491. */
  492. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W)
  493. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V, W>))
  494. constexpr explicit basic_outcome(
  495. basic_outcome<T, U, V, W> &&o,
  496. explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  497. detail::is_nothrow_constructible<error_type, U> &&
  498. detail::is_nothrow_constructible<exception_type, V>)
  499. : base{typename base::compatible_conversion_tag(), static_cast<basic_outcome<T, U, V, W> &&>(o)}
  500. , _ptr(static_cast<typename basic_outcome<T, U, V, W>::exception_type &&>(o._ptr))
  501. {
  502. no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_outcome<T, U, V, W> &&>(o));
  503. }
  504. /*! AWAITING HUGO JSON CONVERSION TOOL
  505. SIGNATURE NOT RECOGNISED
  506. */
  507. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  508. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_compatible_conversion<T, U, V>))
  509. constexpr explicit basic_outcome(
  510. const basic_result<T, U, V> &o,
  511. explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  512. detail::is_nothrow_constructible<error_type, U> &&
  513. detail::is_nothrow_constructible<exception_type>)
  514. : base{typename base::compatible_conversion_tag(), o}
  515. , _ptr()
  516. {
  517. no_value_policy_type::on_outcome_copy_construction(this, o);
  518. }
  519. /*! AWAITING HUGO JSON CONVERSION TOOL
  520. SIGNATURE NOT RECOGNISED
  521. */
  522. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  523. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_compatible_conversion<T, U, V>))
  524. constexpr explicit basic_outcome(
  525. basic_result<T, U, V> &&o,
  526. explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  527. detail::is_nothrow_constructible<error_type, U> &&
  528. detail::is_nothrow_constructible<exception_type>)
  529. : base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
  530. , _ptr()
  531. {
  532. no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
  533. }
  534. /*! AWAITING HUGO JSON CONVERSION TOOL
  535. SIGNATURE NOT RECOGNISED
  536. */
  537. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  538. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_make_error_code_compatible_conversion<T, U, V>))
  539. constexpr explicit basic_outcome(const basic_result<T, U, V> &o,
  540. explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
  541. explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  542. noexcept(make_error_code(std::declval<U>())) &&
  543. detail::is_nothrow_constructible<exception_type>)
  544. : base{typename base::make_error_code_compatible_conversion_tag(), o}
  545. , _ptr()
  546. {
  547. no_value_policy_type::on_outcome_copy_construction(this, o);
  548. }
  549. /*! AWAITING HUGO JSON CONVERSION TOOL
  550. SIGNATURE NOT RECOGNISED
  551. */
  552. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  553. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_make_error_code_compatible_conversion<T, U, V>))
  554. constexpr explicit basic_outcome(basic_result<T, U, V> &&o,
  555. explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
  556. explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&
  557. noexcept(make_error_code(std::declval<U>())) &&
  558. detail::is_nothrow_constructible<exception_type>)
  559. : base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
  560. , _ptr()
  561. {
  562. no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
  563. }
  564. /*! AWAITING HUGO JSON CONVERSION TOOL
  565. SIGNATURE NOT RECOGNISED
  566. */
  567. BOOST_OUTCOME_TEMPLATE(class... Args)
  568. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
  569. constexpr explicit basic_outcome(in_place_type_t<value_type_if_enabled> _, Args &&...args) noexcept(detail::is_nothrow_constructible<value_type, Args...>)
  570. : base{_, static_cast<Args &&>(args)...}
  571. , _ptr()
  572. {
  573. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
  574. }
  575. /*! AWAITING HUGO JSON CONVERSION TOOL
  576. SIGNATURE NOT RECOGNISED
  577. */
  578. BOOST_OUTCOME_TEMPLATE(class U, class... Args)
  579. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<std::initializer_list<U>, Args...>))
  580. constexpr explicit basic_outcome(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il,
  581. Args &&...args) noexcept(detail::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>)
  582. : base{_, il, static_cast<Args &&>(args)...}
  583. , _ptr()
  584. {
  585. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
  586. }
  587. /*! AWAITING HUGO JSON CONVERSION TOOL
  588. SIGNATURE NOT RECOGNISED
  589. */
  590. BOOST_OUTCOME_TEMPLATE(class... Args)
  591. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<Args...>))
  592. constexpr explicit basic_outcome(in_place_type_t<error_type_if_enabled> _, Args &&...args) noexcept(detail::is_nothrow_constructible<error_type, Args...>)
  593. : base{_, static_cast<Args &&>(args)...}
  594. , _ptr()
  595. {
  596. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
  597. }
  598. /*! AWAITING HUGO JSON CONVERSION TOOL
  599. SIGNATURE NOT RECOGNISED
  600. */
  601. BOOST_OUTCOME_TEMPLATE(class U, class... Args)
  602. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<std::initializer_list<U>, Args...>))
  603. constexpr explicit basic_outcome(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il,
  604. Args &&...args) noexcept(detail::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>)
  605. : base{_, il, static_cast<Args &&>(args)...}
  606. , _ptr()
  607. {
  608. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
  609. }
  610. /*! AWAITING HUGO JSON CONVERSION TOOL
  611. SIGNATURE NOT RECOGNISED
  612. */
  613. BOOST_OUTCOME_TEMPLATE(class... Args)
  614. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor<Args...>))
  615. constexpr explicit basic_outcome(in_place_type_t<exception_type_if_enabled> /*unused*/,
  616. Args &&...args) noexcept(detail::is_nothrow_constructible<exception_type, Args...>)
  617. : base()
  618. , _ptr(static_cast<Args &&>(args)...)
  619. {
  620. this->_state._status.set_have_exception(true);
  621. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<exception_type>, static_cast<Args &&>(args)...);
  622. }
  623. /*! AWAITING HUGO JSON CONVERSION TOOL
  624. SIGNATURE NOT RECOGNISED
  625. */
  626. BOOST_OUTCOME_TEMPLATE(class U, class... Args)
  627. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor<std::initializer_list<U>, Args...>))
  628. constexpr explicit basic_outcome(in_place_type_t<exception_type_if_enabled> /*unused*/, std::initializer_list<U> il,
  629. Args &&...args) noexcept(detail::is_nothrow_constructible<exception_type, std::initializer_list<U>, Args...>)
  630. : base()
  631. , _ptr(il, static_cast<Args &&>(args)...)
  632. {
  633. this->_state._status.set_have_exception(true);
  634. no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<exception_type>, il, static_cast<Args &&>(args)...);
  635. }
  636. /*! AWAITING HUGO JSON CONVERSION TOOL
  637. SIGNATURE NOT RECOGNISED
  638. */
  639. BOOST_OUTCOME_TEMPLATE(class A1, class A2, class... Args)
  640. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_error_exception_constructor<A1, A2, Args...>))
  641. constexpr basic_outcome(A1 &&a1, A2 &&a2, Args &&...args) noexcept(
  642. noexcept(typename predicate::template choose_inplace_value_error_exception_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(),
  643. std::declval<Args>()...)))
  644. : basic_outcome(in_place_type<typename predicate::template choose_inplace_value_error_exception_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1),
  645. static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
  646. {
  647. }
  648. /*! AWAITING HUGO JSON CONVERSION TOOL
  649. SIGNATURE NOT RECOGNISED
  650. */
  651. constexpr basic_outcome(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
  652. : base{in_place_type<typename base::_value_type>}
  653. {
  654. hooks::set_spare_storage(this, o.spare_storage());
  655. no_value_policy_type::on_outcome_copy_construction(this, o);
  656. }
  657. /*! AWAITING HUGO JSON CONVERSION TOOL
  658. SIGNATURE NOT RECOGNISED
  659. */
  660. BOOST_OUTCOME_TEMPLATE(class T)
  661. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
  662. constexpr basic_outcome(const success_type<T> &o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
  663. : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(o)}
  664. {
  665. hooks::set_spare_storage(this, o.spare_storage());
  666. no_value_policy_type::on_outcome_copy_construction(this, o);
  667. }
  668. /*! AWAITING HUGO JSON CONVERSION TOOL
  669. SIGNATURE NOT RECOGNISED
  670. */
  671. BOOST_OUTCOME_TEMPLATE(class T)
  672. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
  673. constexpr basic_outcome(success_type<T> &&o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
  674. : base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
  675. {
  676. hooks::set_spare_storage(this, o.spare_storage());
  677. no_value_policy_type::on_outcome_move_construction(this, static_cast<success_type<T> &&>(o));
  678. }
  679. /*! AWAITING HUGO JSON CONVERSION TOOL
  680. SIGNATURE NOT RECOGNISED
  681. */
  682. BOOST_OUTCOME_TEMPLATE(class T)
  683. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
  684. constexpr basic_outcome(const failure_type<T> &o,
  685. error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible<error_type, T>) // NOLINT
  686. : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
  687. , _ptr()
  688. {
  689. hooks::set_spare_storage(this, o.spare_storage());
  690. no_value_policy_type::on_outcome_copy_construction(this, o);
  691. }
  692. /*! AWAITING HUGO JSON CONVERSION TOOL
  693. SIGNATURE NOT RECOGNISED
  694. */
  695. BOOST_OUTCOME_TEMPLATE(class T)
  696. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
  697. constexpr basic_outcome(const failure_type<T> &o,
  698. exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible<exception_type, T>) // NOLINT
  699. : base()
  700. , _ptr(detail::extract_exception_from_failure<exception_type>(o))
  701. {
  702. this->_state._status.set_have_exception(true);
  703. hooks::set_spare_storage(this, o.spare_storage());
  704. no_value_policy_type::on_outcome_copy_construction(this, o);
  705. }
  706. /*! AWAITING HUGO JSON CONVERSION TOOL
  707. SIGNATURE NOT RECOGNISED
  708. */
  709. BOOST_OUTCOME_TEMPLATE(class T)
  710. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_make_error_code_compatible_conversion<void, T, void, void>))
  711. constexpr basic_outcome(const failure_type<T> &o,
  712. explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
  713. explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
  714. : base{in_place_type<typename base::_error_type>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
  715. , _ptr()
  716. {
  717. hooks::set_spare_storage(this, o.spare_storage());
  718. no_value_policy_type::on_outcome_copy_construction(this, o);
  719. }
  720. /*! AWAITING HUGO JSON CONVERSION TOOL
  721. SIGNATURE NOT RECOGNISED
  722. */
  723. BOOST_OUTCOME_TEMPLATE(class T, class U)
  724. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
  725. constexpr basic_outcome(const failure_type<T, U> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(
  726. detail::is_nothrow_constructible<error_type, T> && detail::is_nothrow_constructible<exception_type, U>) // NOLINT
  727. : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
  728. , _ptr(detail::extract_exception_from_failure<exception_type>(o))
  729. {
  730. if(!o.has_error())
  731. {
  732. this->_state._status.set_have_error(false);
  733. }
  734. if(o.has_exception())
  735. {
  736. this->_state._status.set_have_exception(true);
  737. }
  738. hooks::set_spare_storage(this, o.spare_storage());
  739. no_value_policy_type::on_outcome_copy_construction(this, o);
  740. }
  741. /*! AWAITING HUGO JSON CONVERSION TOOL
  742. SIGNATURE NOT RECOGNISED
  743. */
  744. BOOST_OUTCOME_TEMPLATE(class T)
  745. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
  746. constexpr basic_outcome(failure_type<T> &&o,
  747. error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible<error_type, T>) // NOLINT
  748. : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
  749. , _ptr()
  750. {
  751. hooks::set_spare_storage(this, o.spare_storage());
  752. no_value_policy_type::on_outcome_copy_construction(this, o);
  753. }
  754. /*! AWAITING HUGO JSON CONVERSION TOOL
  755. SIGNATURE NOT RECOGNISED
  756. */
  757. BOOST_OUTCOME_TEMPLATE(class T)
  758. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
  759. constexpr basic_outcome(failure_type<T> &&o,
  760. exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible<exception_type, T>) // NOLINT
  761. : base()
  762. , _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T> &&>(o)))
  763. {
  764. this->_state._status.set_have_exception(true);
  765. hooks::set_spare_storage(this, o.spare_storage());
  766. no_value_policy_type::on_outcome_copy_construction(this, o);
  767. }
  768. /*! AWAITING HUGO JSON CONVERSION TOOL
  769. SIGNATURE NOT RECOGNISED
  770. */
  771. BOOST_OUTCOME_TEMPLATE(class T)
  772. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_make_error_code_compatible_conversion<void, T, void, void>))
  773. constexpr basic_outcome(failure_type<T> &&o,
  774. explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
  775. explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
  776. : base{in_place_type<typename base::_error_type>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
  777. , _ptr()
  778. {
  779. hooks::set_spare_storage(this, o.spare_storage());
  780. no_value_policy_type::on_outcome_copy_construction(this, o);
  781. }
  782. /*! AWAITING HUGO JSON CONVERSION TOOL
  783. SIGNATURE NOT RECOGNISED
  784. */
  785. BOOST_OUTCOME_TEMPLATE(class T, class U)
  786. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
  787. constexpr basic_outcome(failure_type<T, U> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(
  788. detail::is_nothrow_constructible<error_type, T> && detail::is_nothrow_constructible<exception_type, U>) // NOLINT
  789. : base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T, U> &&>(o))}
  790. , _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T, U> &&>(o)))
  791. {
  792. if(!o.has_error())
  793. {
  794. this->_state._status.set_have_error(false);
  795. }
  796. if(o.has_exception())
  797. {
  798. this->_state._status.set_have_exception(true);
  799. }
  800. hooks::set_spare_storage(this, o.spare_storage());
  801. no_value_policy_type::on_outcome_move_construction(this, static_cast<failure_type<T, U> &&>(o));
  802. }
  803. /*! AWAITING HUGO JSON CONVERSION TOOL
  804. SIGNATURE NOT RECOGNISED
  805. */
  806. using base::operator==;
  807. using base::operator!=;
  808. /*! AWAITING HUGO JSON CONVERSION TOOL
  809. SIGNATURE NOT RECOGNISED
  810. */
  811. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W)
  812. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<value_type>>() == std::declval<detail::devoid<T>>()), //
  813. BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<error_type>>() == std::declval<detail::devoid<U>>()), //
  814. BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<exception_type>>() == std::declval<detail::devoid<V>>()))
  815. constexpr bool operator==(const basic_outcome<T, U, V, W> &o) const noexcept( //
  816. noexcept(std::declval<detail::devoid<value_type>>() == std::declval<detail::devoid<T>>()) //
  817. && noexcept(std::declval<detail::devoid<error_type>>() == std::declval<detail::devoid<U>>()) //
  818. && noexcept(std::declval<detail::devoid<exception_type>>() == std::declval<detail::devoid<V>>()))
  819. {
  820. if(this->_state._status.have_value() && o._state._status.have_value())
  821. {
  822. return this->_state._value == o._state._value; // NOLINT
  823. }
  824. if(this->_state._status.have_error() && o._state._status.have_error() //
  825. && this->_state._status.have_exception() && o._state._status.have_exception())
  826. {
  827. return this->_state._error == o._state._error && this->_ptr == o._ptr;
  828. }
  829. if(this->_state._status.have_error() && o._state._status.have_error())
  830. {
  831. return this->_state._error == o._state._error;
  832. }
  833. if(this->_state._status.have_exception() && o._state._status.have_exception())
  834. {
  835. return this->_ptr == o._ptr;
  836. }
  837. return false;
  838. }
  839. /*! AWAITING HUGO JSON CONVERSION TOOL
  840. SIGNATURE NOT RECOGNISED
  841. */
  842. BOOST_OUTCOME_TEMPLATE(class T, class U)
  843. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<error_type>() == std::declval<T>()), //
  844. BOOST_OUTCOME_TEXPR(std::declval<exception_type>() == std::declval<U>()))
  845. constexpr bool operator==(const failure_type<T, U> &o) const noexcept( //
  846. noexcept(std::declval<error_type>() == std::declval<T>()) && noexcept(std::declval<exception_type>() == std::declval<U>()))
  847. {
  848. if(this->_state._status.have_error() && o._state._status.have_error() //
  849. && this->_state._status.have_exception() && o._state._status.have_exception())
  850. {
  851. return this->_state._error == o.error() && this->_ptr == o.exception();
  852. }
  853. if(this->_state._status.have_error() && o._state._status.have_error())
  854. {
  855. return this->_state._error == o.error();
  856. }
  857. if(this->_state._status.have_exception() && o._state._status.have_exception())
  858. {
  859. return this->_ptr == o.exception();
  860. }
  861. return false;
  862. }
  863. /*! AWAITING HUGO JSON CONVERSION TOOL
  864. SIGNATURE NOT RECOGNISED
  865. */
  866. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, class W)
  867. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<value_type>>() != std::declval<detail::devoid<T>>()), //
  868. BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<error_type>>() != std::declval<detail::devoid<U>>()), //
  869. BOOST_OUTCOME_TEXPR(std::declval<detail::devoid<exception_type>>() != std::declval<detail::devoid<V>>()))
  870. constexpr bool operator!=(const basic_outcome<T, U, V, W> &o) const noexcept( //
  871. noexcept(std::declval<detail::devoid<value_type>>() != std::declval<detail::devoid<T>>()) //
  872. && noexcept(std::declval<detail::devoid<error_type>>() != std::declval<detail::devoid<U>>()) //
  873. && noexcept(std::declval<detail::devoid<exception_type>>() != std::declval<detail::devoid<V>>()))
  874. {
  875. if(this->_state._status.have_value() && o._state._status.have_value())
  876. {
  877. return this->_state._value != o._state._value; // NOLINT
  878. }
  879. if(this->_state._status.have_error() && o._state._status.have_error() //
  880. && this->_state._status.have_exception() && o._state._status.have_exception())
  881. {
  882. return this->_state._error != o._state._error || this->_ptr != o._ptr;
  883. }
  884. if(this->_state._status.have_error() && o._state._status.have_error())
  885. {
  886. return this->_state._error != o._state._error;
  887. }
  888. if(this->_state._status.have_exception() && o._state._status.have_exception())
  889. {
  890. return this->_ptr != o._ptr;
  891. }
  892. return true;
  893. }
  894. /*! AWAITING HUGO JSON CONVERSION TOOL
  895. SIGNATURE NOT RECOGNISED
  896. */
  897. BOOST_OUTCOME_TEMPLATE(class T, class U)
  898. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<error_type>() != std::declval<T>()), //
  899. BOOST_OUTCOME_TEXPR(std::declval<exception_type>() != std::declval<U>()))
  900. constexpr bool operator!=(const failure_type<T, U> &o) const noexcept( //
  901. noexcept(std::declval<error_type>() == std::declval<T>()) && noexcept(std::declval<exception_type>() == std::declval<U>()))
  902. {
  903. if(this->_state._status.have_error() && o._state._status.have_error() //
  904. && this->_state._status.have_exception() && o._state._status.have_exception())
  905. {
  906. return this->_state._error != o.error() || this->_ptr != o.exception();
  907. }
  908. if(this->_state._status.have_error() && o._state._status.have_error())
  909. {
  910. return this->_state._error != o.error();
  911. }
  912. if(this->_state._status.have_exception() && o._state._status.have_exception())
  913. {
  914. return this->_ptr != o.exception();
  915. }
  916. return true;
  917. }
  918. /*! AWAITING HUGO JSON CONVERSION TOOL
  919. SIGNATURE NOT RECOGNISED
  920. */
  921. constexpr void swap(basic_outcome &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
  922. && (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value) //
  923. && (std::is_void<exception_type>::value || detail::is_nothrow_swappable<exception_type>::value))
  924. {
  925. #ifndef BOOST_NO_EXCEPTIONS
  926. constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
  927. constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
  928. constexpr bool exception_throws = !std::is_void<exception_type>::value && !detail::is_nothrow_swappable<exception_type>::value;
  929. #ifdef _MSC_VER
  930. #pragma warning(push)
  931. #pragma warning(disable : 4127) // conditional expression is constant
  932. #endif
  933. if(!exception_throws && !value_throws && !error_throws)
  934. {
  935. // Simples
  936. this->_state.swap(o._state);
  937. using std::swap;
  938. swap(this->_ptr, o._ptr);
  939. return;
  940. }
  941. struct some_type
  942. {
  943. basic_outcome &a, &b;
  944. bool exceptioned{false};
  945. bool all_good{false};
  946. ~some_type()
  947. {
  948. if(!this->all_good)
  949. {
  950. // We lost one of the values
  951. this->a._state._status.set_have_lost_consistency(true);
  952. this->b._state._status.set_have_lost_consistency(true);
  953. return;
  954. }
  955. if(this->exceptioned)
  956. {
  957. // The value + error swap threw an exception. Try to swap back _ptr
  958. try
  959. {
  960. strong_swap(this->all_good, this->a._ptr, this->b._ptr);
  961. }
  962. catch(...)
  963. {
  964. // We lost one of the values
  965. this->a._state._status.set_have_lost_consistency(true);
  966. this->b._state._status.set_have_lost_consistency(true);
  967. // throw away second exception
  968. }
  969. // Prevent has_value() == has_error() or has_value() == has_exception()
  970. auto check = [](basic_outcome *t)
  971. {
  972. if(t->has_value() && (t->has_error() || t->has_exception()))
  973. {
  974. t->_state._status.set_have_error(false).set_have_exception(false);
  975. t->_state._status.set_have_lost_consistency(true);
  976. }
  977. if(!t->has_value() && !(t->has_error() || t->has_exception()))
  978. {
  979. // Choose error, for no particular reason
  980. t->_state._status.set_have_error(true).set_have_lost_consistency(true);
  981. }
  982. };
  983. check(&this->a);
  984. check(&this->b);
  985. }
  986. }
  987. } some_type_value{*this, o};
  988. strong_swap(some_type_value.all_good, this->_ptr, o._ptr);
  989. some_type_value.exceptioned = true;
  990. this->_state.swap(o._state);
  991. some_type_value.exceptioned = false;
  992. #ifdef _MSC_VER
  993. #pragma warning(pop)
  994. #endif
  995. #else
  996. this->_state.swap(o._state);
  997. using std::swap;
  998. swap(this->_ptr, o._ptr);
  999. #endif
  1000. }
  1001. /*! AWAITING HUGO JSON CONVERSION TOOL
  1002. SIGNATURE NOT RECOGNISED
  1003. */
  1004. failure_type<error_type, exception_type> as_failure() const &
  1005. {
  1006. if(this->has_error() && this->has_exception())
  1007. {
  1008. return failure_type<error_type, exception_type>(this->assume_error(), this->assume_exception(), hooks::spare_storage(this));
  1009. }
  1010. if(this->has_exception())
  1011. {
  1012. return failure_type<error_type, exception_type>(in_place_type<exception_type>, this->assume_exception(), hooks::spare_storage(this));
  1013. }
  1014. return failure_type<error_type, exception_type>(in_place_type<error_type>, this->assume_error(), hooks::spare_storage(this));
  1015. }
  1016. /*! AWAITING HUGO JSON CONVERSION TOOL
  1017. SIGNATURE NOT RECOGNISED
  1018. */
  1019. failure_type<error_type, exception_type> as_failure() &&
  1020. {
  1021. this->_state._status.set_have_moved_from(true);
  1022. if(this->has_error() && this->has_exception())
  1023. {
  1024. return failure_type<error_type, exception_type>(static_cast<S &&>(this->assume_error()), static_cast<P &&>(this->assume_exception()),
  1025. hooks::spare_storage(this));
  1026. }
  1027. if(this->has_exception())
  1028. {
  1029. return failure_type<error_type, exception_type>(in_place_type<exception_type>, static_cast<P &&>(this->assume_exception()), hooks::spare_storage(this));
  1030. }
  1031. return failure_type<error_type, exception_type>(in_place_type<error_type>, static_cast<S &&>(this->assume_error()), hooks::spare_storage(this));
  1032. }
  1033. #ifdef __APPLE__
  1034. failure_type<error_type, exception_type> _xcode_workaround_as_failure() &&;
  1035. #endif
  1036. };
  1037. // C++ 20 operator== rewriting should take care of this for us, indeed
  1038. // if we don't disable it, we cause Concept recursion to infinity!
  1039. #if __cplusplus < 202000L && !_HAS_CXX20
  1040. /*! AWAITING HUGO JSON CONVERSION TOOL
  1041. SIGNATURE NOT RECOGNISED
  1042. */
  1043. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, //
  1044. class R, class S, class P, class N)
  1045. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<basic_outcome<R, S, P, N>>() == std::declval<basic_result<T, U, V>>()))
  1046. constexpr inline bool operator==(const basic_result<T, U, V> &a, const basic_outcome<R, S, P, N> &b) noexcept( //
  1047. noexcept(std::declval<basic_outcome<R, S, P, N>>() == std::declval<basic_result<T, U, V>>()))
  1048. {
  1049. return b == a;
  1050. }
  1051. #endif
  1052. /*! AWAITING HUGO JSON CONVERSION TOOL
  1053. SIGNATURE NOT RECOGNISED
  1054. */
  1055. BOOST_OUTCOME_TEMPLATE(class T, class U, class V, //
  1056. class R, class S, class P, class N)
  1057. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(std::declval<basic_outcome<R, S, P, N>>() != std::declval<basic_result<T, U, V>>()))
  1058. constexpr inline bool operator!=(const basic_result<T, U, V> &a, const basic_outcome<R, S, P, N> &b) noexcept( //
  1059. noexcept(std::declval<basic_outcome<R, S, P, N>>() != std::declval<basic_result<T, U, V>>()))
  1060. {
  1061. return b != a;
  1062. }
  1063. /*! AWAITING HUGO JSON CONVERSION TOOL
  1064. SIGNATURE NOT RECOGNISED
  1065. */
  1066. template <class R, class S, class P, class N> inline void swap(basic_outcome<R, S, P, N> &a, basic_outcome<R, S, P, N> &b) noexcept(noexcept(a.swap(b)))
  1067. {
  1068. a.swap(b);
  1069. }
  1070. namespace hooks
  1071. {
  1072. /*! AWAITING HUGO JSON CONVERSION TOOL
  1073. SIGNATURE NOT RECOGNISED
  1074. */
  1075. template <class R, class S, class P, class NoValuePolicy, class U>
  1076. constexpr inline void override_outcome_exception(basic_outcome<R, S, P, NoValuePolicy> *o, U &&v) noexcept
  1077. {
  1078. o->_ptr = static_cast<U &&>(v); // NOLINT
  1079. o->_state._status.set_have_exception(true);
  1080. }
  1081. } // namespace hooks
  1082. BOOST_OUTCOME_V2_NAMESPACE_END
  1083. #if defined(_MSC_VER) && !defined(__clang__)
  1084. #pragma warning(pop)
  1085. #endif
  1086. #ifdef __clang__
  1087. #pragma clang diagnostic pop
  1088. #endif
  1089. #include "detail/basic_outcome_exception_observers_impl.hpp"
  1090. #if !defined(NDEBUG)
  1091. BOOST_OUTCOME_V2_NAMESPACE_BEGIN
  1092. // Check is trivial in all ways except default constructibility and standard layout
  1093. // static_assert(std::is_trivial<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivial!");
  1094. // static_assert(std::is_trivially_default_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially default
  1095. // constructible!");
  1096. static_assert(std::is_trivially_copyable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially copyable!");
  1097. static_assert(std::is_trivially_assignable<basic_outcome<int, long, double, policy::all_narrow>, basic_outcome<int, long, double, policy::all_narrow>>::value,
  1098. "outcome<int> is not trivially assignable!");
  1099. static_assert(std::is_trivially_destructible<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially destructible!");
  1100. static_assert(std::is_trivially_copy_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value,
  1101. "outcome<int> is not trivially copy constructible!");
  1102. static_assert(std::is_trivially_move_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value,
  1103. "outcome<int> is not trivially move constructible!");
  1104. static_assert(std::is_trivially_copy_assignable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially copy assignable!");
  1105. static_assert(std::is_trivially_move_assignable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially move assignable!");
  1106. // Can't be standard layout as non-static member data is defined in more than one inherited class
  1107. // static_assert(std::is_standard_layout<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not a standard layout type!");
  1108. BOOST_OUTCOME_V2_NAMESPACE_END
  1109. #endif
  1110. #endif