basic_result.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /* A very simple result type
  2. (C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (14 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_RESULT_HPP
  26. #define BOOST_OUTCOME_BASIC_RESULT_HPP
  27. #include "config.hpp"
  28. #include "convert.hpp"
  29. #include "detail/basic_result_final.hpp"
  30. #include "policy/all_narrow.hpp"
  31. #include "policy/terminate.hpp"
  32. #ifdef __clang__
  33. #pragma clang diagnostic push
  34. #pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
  35. #endif
  36. BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
  37. template <class R, class S, class NoValuePolicy> //
  38. #if !defined(__GNUC__) || __GNUC__ >= 10 // GCC's constraints implementation is buggy
  39. BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<S> && (std::is_void<S>::value || std::is_default_constructible<S>::value)) //
  40. #endif
  41. class basic_result;
  42. namespace detail
  43. {
  44. // These are reused by basic_outcome to save load on the compiler
  45. template <class value_type, class error_type> struct result_predicates
  46. {
  47. // Predicate for the implicit constructors to be available. Weakened to allow result<int, C enum>.
  48. static constexpr bool implicit_constructors_enabled = //
  49. !(trait::is_error_type<std::decay_t<value_type>>::value && trait::is_error_type<std::decay_t<error_type>>::value) // both value and error types are not whitelisted error types
  50. && ((!detail::is_implicitly_constructible<value_type, error_type> && !detail::is_implicitly_constructible<error_type, value_type>) // if value and error types cannot be constructed into one another
  51. || (trait::is_error_type<std::decay_t<error_type>>::value // if error type is a whitelisted error type
  52. && !detail::is_implicitly_constructible<error_type, value_type> // AND which cannot be constructed from the value type
  53. && std::is_integral<value_type>::value)); // AND the value type is some integral type
  54. // Predicate for the value converting constructor to be available. Weakened to allow result<int, C enum>.
  55. template <class T>
  56. static constexpr bool enable_value_converting_constructor = //
  57. implicit_constructors_enabled //
  58. && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
  59. && !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
  60. && ((detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T>) // is unambiguously for value type
  61. || (std::is_same<value_type, std::decay_t<T>>::value // OR is my value type exactly
  62. && detail::is_implicitly_constructible<value_type, T>) ); // and my value type is constructible from this ref form of T
  63. // Predicate for the error converting constructor to be available. Weakened to allow result<int, C enum>.
  64. template <class T>
  65. static constexpr bool enable_error_converting_constructor = //
  66. implicit_constructors_enabled //
  67. && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
  68. && !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
  69. && ((!detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T>) // is unambiguously for error type
  70. || (std::is_same<error_type, std::decay_t<T>>::value // OR is my error type exactly
  71. && detail::is_implicitly_constructible<error_type, T>) ); // and my error type is constructible from this ref form of T
  72. // Predicate for the error condition converting constructor to be available.
  73. template <class ErrorCondEnum>
  74. static constexpr bool enable_error_condition_converting_constructor = //
  75. !is_in_place_type_t<std::decay_t<ErrorCondEnum>>::value // not in place construction
  76. && trait::is_error_type_enum<error_type, std::decay_t<ErrorCondEnum>>::value // is an error condition enum
  77. /*&& !detail::is_implicitly_constructible<value_type, ErrorCondEnum> && !detail::is_implicitly_constructible<error_type, ErrorCondEnum>*/; // not constructible via any other means
  78. // Predicate for the converting constructor from a compatible input to be available.
  79. template <class T, class U, class V>
  80. static constexpr bool enable_compatible_conversion = //
  81. (std::is_void<T>::value || detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // if our value types are constructible
  82. &&(std::is_void<U>::value || detail::is_explicitly_constructible<error_type, typename basic_result<T, U, V>::error_type>) // if our error types are constructible
  83. ;
  84. // Predicate for the converting constructor from a make_error_code() of the input to be available.
  85. template <class T, class U, class V>
  86. static constexpr bool enable_make_error_code_compatible_conversion = //
  87. trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
  88. && !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
  89. && (std::is_void<T>::value || detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
  90. &&detail::is_explicitly_constructible<error_type, typename trait::is_error_code_available<U>::type>; // and our error type is constructible from a make_error_code()
  91. // Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
  92. template <class T, class U, class V>
  93. static constexpr bool enable_make_exception_ptr_compatible_conversion = //
  94. trait::is_exception_ptr_available<std::decay_t<error_type>>::value // if error type has an exception ptr
  95. && !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
  96. && (std::is_void<T>::value || detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
  97. &&detail::is_explicitly_constructible<error_type, typename trait::is_exception_ptr_available<U>::type>; // and our error type is constructible from a make_exception_ptr()
  98. // Predicate for the implicit converting inplace constructor from a compatible input to be available.
  99. struct disable_inplace_value_error_constructor;
  100. template <class... Args>
  101. using choose_inplace_value_error_constructor = std::conditional_t< //
  102. std::is_constructible<value_type, Args...>::value && std::is_constructible<error_type, Args...>::value, //
  103. disable_inplace_value_error_constructor, //
  104. std::conditional_t< //
  105. std::is_constructible<value_type, Args...>::value, //
  106. value_type, //
  107. std::conditional_t< //
  108. std::is_constructible<error_type, Args...>::value, //
  109. error_type, //
  110. disable_inplace_value_error_constructor>>>;
  111. template <class... Args>
  112. static constexpr bool enable_inplace_value_error_constructor = implicit_constructors_enabled //
  113. && !std::is_same<choose_inplace_value_error_constructor<Args...>, disable_inplace_value_error_constructor>::value;
  114. };
  115. template <class T, class U> constexpr inline const U &extract_value_from_success(const success_type<U> &v) { return v.value(); }
  116. template <class T, class U> constexpr inline U &&extract_value_from_success(success_type<U> &&v) { return static_cast<success_type<U> &&>(v).value(); }
  117. template <class T> constexpr inline T extract_value_from_success(const success_type<void> & /*unused*/) { return T{}; }
  118. template <class T, class U, class V> constexpr inline const U &extract_error_from_failure(const failure_type<U, V> &v) { return v.error(); }
  119. template <class T, class U, class V> constexpr inline U &&extract_error_from_failure(failure_type<U, V> &&v) { return static_cast<failure_type<U, V> &&>(v).error(); }
  120. template <class T, class V> constexpr inline T extract_error_from_failure(const failure_type<void, V> & /*unused*/) { return T{}; }
  121. template <class T> struct is_basic_result
  122. {
  123. static constexpr bool value = false;
  124. };
  125. template <class R, class S, class T> struct is_basic_result<basic_result<R, S, T>>
  126. {
  127. static constexpr bool value = true;
  128. };
  129. } // namespace detail
  130. /*! AWAITING HUGO JSON CONVERSION TOOL
  131. type alias template <class T> is_basic_result. Potential doc page: `is_basic_result<T>`
  132. */
  133. template <class T> using is_basic_result = detail::is_basic_result<std::decay_t<T>>;
  134. /*! AWAITING HUGO JSON CONVERSION TOOL
  135. SIGNATURE NOT RECOGNISED
  136. */
  137. template <class T> static constexpr bool is_basic_result_v = detail::is_basic_result<std::decay_t<T>>::value;
  138. /*! AWAITING HUGO JSON CONVERSION TOOL
  139. SIGNATURE NOT RECOGNISED
  140. */
  141. namespace hooks
  142. {
  143. /*! AWAITING HUGO JSON CONVERSION TOOL
  144. SIGNATURE NOT RECOGNISED
  145. */
  146. template <class T, class U> constexpr inline void hook_result_construction(T * /*unused*/, U && /*unused*/) noexcept {}
  147. /*! AWAITING HUGO JSON CONVERSION TOOL
  148. SIGNATURE NOT RECOGNISED
  149. */
  150. template <class T, class U> constexpr inline void hook_result_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
  151. /*! AWAITING HUGO JSON CONVERSION TOOL
  152. SIGNATURE NOT RECOGNISED
  153. */
  154. template <class T, class U> constexpr inline void hook_result_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
  155. /*! AWAITING HUGO JSON CONVERSION TOOL
  156. SIGNATURE NOT RECOGNISED
  157. */
  158. template <class T, class U, class... Args> constexpr inline void hook_result_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept {}
  159. /*! AWAITING HUGO JSON CONVERSION TOOL
  160. SIGNATURE NOT RECOGNISED
  161. */
  162. template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_final<R, S, NoValuePolicy> *r) noexcept { return (r->_state._status >> detail::status_2byte_shift) & 0xffff; }
  163. /*! AWAITING HUGO JSON CONVERSION TOOL
  164. SIGNATURE NOT RECOGNISED
  165. */
  166. template <class R, class S, class NoValuePolicy> constexpr inline void set_spare_storage(detail::basic_result_final<R, S, NoValuePolicy> *r, uint16_t v) noexcept { r->_state._status |= (v << detail::status_2byte_shift); }
  167. } // namespace hooks
  168. /*! AWAITING HUGO JSON CONVERSION TOOL
  169. type definition template <class R, class S, class NoValuePolicy> basic_result. Potential doc page: `basic_result<T, E, NoValuePolicy>`
  170. */
  171. template <class R, class S, class NoValuePolicy> //
  172. #if !defined(__GNUC__) || __GNUC__ >= 10 // GCC's constraints implementation is buggy
  173. BOOST_OUTCOME_REQUIRES(trait::type_can_be_used_in_basic_result<R> &&trait::type_can_be_used_in_basic_result<S> && (std::is_void<S>::value || std::is_default_constructible<S>::value)) //
  174. #endif
  175. class BOOST_OUTCOME_NODISCARD basic_result : public detail::basic_result_final<R, S, NoValuePolicy>
  176. {
  177. static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
  178. static_assert(trait::type_can_be_used_in_basic_result<S>, "The type S cannot be used in a basic_result");
  179. static_assert(std::is_void<S>::value || std::is_default_constructible<S>::value, "The type S must be void or default constructible");
  180. using base = detail::basic_result_final<R, S, NoValuePolicy>;
  181. struct implicit_constructors_disabled_tag
  182. {
  183. };
  184. struct value_converting_constructor_tag
  185. {
  186. };
  187. struct error_converting_constructor_tag
  188. {
  189. };
  190. struct error_condition_converting_constructor_tag
  191. {
  192. };
  193. struct explicit_valueornone_converting_constructor_tag
  194. {
  195. };
  196. struct explicit_valueorerror_converting_constructor_tag
  197. {
  198. };
  199. struct explicit_compatible_copy_conversion_tag
  200. {
  201. };
  202. struct explicit_compatible_move_conversion_tag
  203. {
  204. };
  205. struct explicit_make_error_code_compatible_copy_conversion_tag
  206. {
  207. };
  208. struct explicit_make_error_code_compatible_move_conversion_tag
  209. {
  210. };
  211. struct explicit_make_exception_ptr_compatible_copy_conversion_tag
  212. {
  213. };
  214. struct explicit_make_exception_ptr_compatible_move_conversion_tag
  215. {
  216. };
  217. public:
  218. using value_type = R;
  219. using error_type = S;
  220. using value_type_if_enabled = typename base::_value_type;
  221. using error_type_if_enabled = typename base::_error_type;
  222. template <class T, class U = S, class V = NoValuePolicy> using rebind = basic_result<T, U, V>;
  223. protected:
  224. // Requirement predicates for result.
  225. struct predicate
  226. {
  227. using base = detail::result_predicates<value_type, error_type>;
  228. // Predicate for any constructors to be available at all
  229. static constexpr bool constructors_enabled = !std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value;
  230. // Predicate for implicit constructors to be available at all
  231. static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
  232. // Predicate for the value converting constructor to be available.
  233. template <class T>
  234. static constexpr bool enable_value_converting_constructor = //
  235. constructors_enabled //
  236. && !std::is_same<std::decay_t<T>, basic_result>::value // not my type
  237. && base::template enable_value_converting_constructor<T>;
  238. // Predicate for the error converting constructor to be available.
  239. template <class T>
  240. static constexpr bool enable_error_converting_constructor = //
  241. constructors_enabled //
  242. && !std::is_same<std::decay_t<T>, basic_result>::value // not my type
  243. && base::template enable_error_converting_constructor<T>;
  244. // Predicate for the error condition converting constructor to be available.
  245. template <class ErrorCondEnum>
  246. static constexpr bool enable_error_condition_converting_constructor = //
  247. constructors_enabled //
  248. && !std::is_same<std::decay_t<ErrorCondEnum>, basic_result>::value // not my type
  249. && base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
  250. // Predicate for the converting constructor from a compatible input to be available.
  251. template <class T, class U, class V>
  252. static constexpr bool enable_compatible_conversion = //
  253. constructors_enabled //
  254. && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
  255. && base::template enable_compatible_conversion<T, U, V>;
  256. // Predicate for the converting constructor from a make_error_code() of the input to be available.
  257. template <class T, class U, class V>
  258. static constexpr bool enable_make_error_code_compatible_conversion = //
  259. constructors_enabled //
  260. && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
  261. && base::template enable_make_error_code_compatible_conversion<T, U, V>;
  262. // Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
  263. template <class T, class U, class V>
  264. static constexpr bool enable_make_exception_ptr_compatible_conversion = //
  265. constructors_enabled //
  266. && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
  267. && base::template enable_make_exception_ptr_compatible_conversion<T, U, V>;
  268. // Predicate for the inplace construction of value to be available.
  269. template <class... Args>
  270. static constexpr bool enable_inplace_value_constructor = //
  271. constructors_enabled //
  272. && (std::is_void<value_type>::value //
  273. || std::is_constructible<value_type, Args...>::value);
  274. // Predicate for the inplace construction of error to be available.
  275. template <class... Args>
  276. static constexpr bool enable_inplace_error_constructor = //
  277. constructors_enabled //
  278. && (std::is_void<error_type>::value //
  279. || std::is_constructible<error_type, Args...>::value);
  280. // Predicate for the implicit converting inplace constructor to be available.
  281. template <class... Args>
  282. static constexpr bool enable_inplace_value_error_constructor = //
  283. constructors_enabled //
  284. &&base::template enable_inplace_value_error_constructor<Args...>;
  285. template <class... Args> using choose_inplace_value_error_constructor = typename base::template choose_inplace_value_error_constructor<Args...>;
  286. };
  287. public:
  288. /*! AWAITING HUGO JSON CONVERSION TOOL
  289. SIGNATURE NOT RECOGNISED
  290. */
  291. basic_result() = delete;
  292. /*! AWAITING HUGO JSON CONVERSION TOOL
  293. SIGNATURE NOT RECOGNISED
  294. */
  295. basic_result(basic_result && /*unused*/) = default; // NOLINT
  296. /*! AWAITING HUGO JSON CONVERSION TOOL
  297. SIGNATURE NOT RECOGNISED
  298. */
  299. basic_result(const basic_result & /*unused*/) = default;
  300. /*! AWAITING HUGO JSON CONVERSION TOOL
  301. SIGNATURE NOT RECOGNISED
  302. */
  303. basic_result &operator=(basic_result && /*unused*/) = default; // NOLINT
  304. /*! AWAITING HUGO JSON CONVERSION TOOL
  305. SIGNATURE NOT RECOGNISED
  306. */
  307. basic_result &operator=(const basic_result & /*unused*/) = default;
  308. ~basic_result() = default;
  309. /*! AWAITING HUGO JSON CONVERSION TOOL
  310. SIGNATURE NOT RECOGNISED
  311. */
  312. BOOST_OUTCOME_TEMPLATE(class Arg, class... Args)
  313. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!predicate::constructors_enabled && (sizeof...(Args) >= 0)))
  314. basic_result(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_result<T, T> is NOT SUPPORTED, see docs!
  315. /*! AWAITING HUGO JSON CONVERSION TOOL
  316. SIGNATURE NOT RECOGNISED
  317. */
  318. BOOST_OUTCOME_TEMPLATE(class T)
  319. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
  320. && (detail::is_implicitly_constructible<value_type, T> || detail::is_implicitly_constructible<error_type, T>) )))
  321. basic_result(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) = delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
  322. /*! AWAITING HUGO JSON CONVERSION TOOL
  323. SIGNATURE NOT RECOGNISED
  324. */
  325. BOOST_OUTCOME_TEMPLATE(class T)
  326. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
  327. constexpr basic_result(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
  328. : base{in_place_type<typename base::value_type>, static_cast<T &&>(t)}
  329. {
  330. using namespace hooks;
  331. hook_result_construction(this, static_cast<T &&>(t));
  332. }
  333. /*! AWAITING HUGO JSON CONVERSION TOOL
  334. SIGNATURE NOT RECOGNISED
  335. */
  336. BOOST_OUTCOME_TEMPLATE(class T)
  337. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
  338. constexpr basic_result(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
  339. : base{in_place_type<typename base::error_type>, static_cast<T &&>(t)}
  340. {
  341. using namespace hooks;
  342. hook_result_construction(this, static_cast<T &&>(t));
  343. }
  344. /*! AWAITING HUGO JSON CONVERSION TOOL
  345. SIGNATURE NOT RECOGNISED
  346. */
  347. BOOST_OUTCOME_TEMPLATE(class ErrorCondEnum)
  348. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
  349. BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
  350. constexpr basic_result(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
  351. : base{in_place_type<typename base::error_type>, make_error_code(t)}
  352. {
  353. using namespace hooks;
  354. hook_result_construction(this, static_cast<ErrorCondEnum &&>(t));
  355. }
  356. /*! AWAITING HUGO JSON CONVERSION TOOL
  357. SIGNATURE NOT RECOGNISED
  358. */
  359. BOOST_OUTCOME_TEMPLATE(class T)
  360. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error<basic_result, std::decay_t<T>>::enable_result_inputs || !is_basic_result_v<T>), //
  361. BOOST_OUTCOME_TEXPR(convert::value_or_error<basic_result, std::decay_t<T>>{}(std::declval<T>())))
  362. constexpr explicit basic_result(T &&o, explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
  363. : basic_result{convert::value_or_error<basic_result, std::decay_t<T>>{}(static_cast<T &&>(o))}
  364. {
  365. }
  366. /*! AWAITING HUGO JSON CONVERSION TOOL
  367. SIGNATURE NOT RECOGNISED
  368. */
  369. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  370. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
  371. constexpr explicit basic_result(const basic_result<T, U, V> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&std::is_nothrow_constructible<error_type, U>::value)
  372. : base{typename base::compatible_conversion_tag(), o}
  373. {
  374. using namespace hooks;
  375. hook_result_copy_construction(this, o);
  376. }
  377. /*! AWAITING HUGO JSON CONVERSION TOOL
  378. SIGNATURE NOT RECOGNISED
  379. */
  380. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  381. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
  382. constexpr explicit basic_result(basic_result<T, U, V> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&std::is_nothrow_constructible<error_type, U>::value)
  383. : base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
  384. {
  385. using namespace hooks;
  386. hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
  387. }
  388. /*! AWAITING HUGO JSON CONVERSION TOOL
  389. SIGNATURE NOT RECOGNISED
  390. */
  391. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  392. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
  393. constexpr explicit basic_result(const basic_result<T, U, V> &o, explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ = explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&noexcept(make_error_code(std::declval<U>())))
  394. : base{typename base::make_error_code_compatible_conversion_tag(), o}
  395. {
  396. using namespace hooks;
  397. hook_result_copy_construction(this, o);
  398. }
  399. /*! AWAITING HUGO JSON CONVERSION TOOL
  400. SIGNATURE NOT RECOGNISED
  401. */
  402. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  403. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
  404. constexpr explicit basic_result(basic_result<T, U, V> &&o, explicit_make_error_code_compatible_move_conversion_tag /*unused*/ = explicit_make_error_code_compatible_move_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&noexcept(make_error_code(std::declval<U>())))
  405. : base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
  406. {
  407. using namespace hooks;
  408. hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
  409. }
  410. /*! AWAITING HUGO JSON CONVERSION TOOL
  411. SIGNATURE NOT RECOGNISED
  412. */
  413. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  414. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
  415. constexpr explicit basic_result(const basic_result<T, U, V> &o, explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ = explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&noexcept(make_exception_ptr(std::declval<U>())))
  416. : base{typename base::make_exception_ptr_compatible_conversion_tag(), o}
  417. {
  418. using namespace hooks;
  419. hook_result_copy_construction(this, o);
  420. }
  421. /*! AWAITING HUGO JSON CONVERSION TOOL
  422. SIGNATURE NOT RECOGNISED
  423. */
  424. BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
  425. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
  426. constexpr explicit basic_result(basic_result<T, U, V> &&o, explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ = explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(std::is_nothrow_constructible<value_type, T>::value &&noexcept(make_exception_ptr(std::declval<U>())))
  427. : base{typename base::make_exception_ptr_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
  428. {
  429. using namespace hooks;
  430. hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
  431. }
  432. /*! AWAITING HUGO JSON CONVERSION TOOL
  433. SIGNATURE NOT RECOGNISED
  434. */
  435. BOOST_OUTCOME_TEMPLATE(class... Args)
  436. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
  437. constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args...>::value)
  438. : base{_, static_cast<Args &&>(args)...}
  439. {
  440. using namespace hooks;
  441. hook_result_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
  442. }
  443. /*! AWAITING HUGO JSON CONVERSION TOOL
  444. SIGNATURE NOT RECOGNISED
  445. */
  446. BOOST_OUTCOME_TEMPLATE(class U, class... Args)
  447. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<std::initializer_list<U>, Args...>))
  448. constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>::value)
  449. : base{_, il, static_cast<Args &&>(args)...}
  450. {
  451. using namespace hooks;
  452. hook_result_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
  453. }
  454. /*! AWAITING HUGO JSON CONVERSION TOOL
  455. SIGNATURE NOT RECOGNISED
  456. */
  457. BOOST_OUTCOME_TEMPLATE(class... Args)
  458. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<Args...>))
  459. constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(std::is_nothrow_constructible<error_type, Args...>::value)
  460. : base{_, static_cast<Args &&>(args)...}
  461. {
  462. using namespace hooks;
  463. hook_result_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
  464. }
  465. /*! AWAITING HUGO JSON CONVERSION TOOL
  466. SIGNATURE NOT RECOGNISED
  467. */
  468. BOOST_OUTCOME_TEMPLATE(class U, class... Args)
  469. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<std::initializer_list<U>, Args...>))
  470. constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il, Args &&... args) noexcept(std::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>::value)
  471. : base{_, il, static_cast<Args &&>(args)...}
  472. {
  473. using namespace hooks;
  474. hook_result_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
  475. }
  476. /*! AWAITING HUGO JSON CONVERSION TOOL
  477. SIGNATURE NOT RECOGNISED
  478. */
  479. BOOST_OUTCOME_TEMPLATE(class A1, class A2, class... Args)
  480. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_error_constructor<A1, A2, Args...>))
  481. constexpr basic_result(A1 &&a1, A2 &&a2, Args &&... args) noexcept(noexcept(typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(), std::declval<Args>()...)))
  482. : basic_result(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1), static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
  483. {
  484. /* I was a little surprised that the below is needed given that we forward to another constructor.
  485. But it turns out that ADL only fires on the first constructor for some reason.
  486. */
  487. using namespace hooks;
  488. // hook_result_in_place_construction(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, this);
  489. }
  490. /*! AWAITING HUGO JSON CONVERSION TOOL
  491. SIGNATURE NOT RECOGNISED
  492. */
  493. constexpr basic_result(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
  494. : base{in_place_type<value_type_if_enabled>}
  495. {
  496. using namespace hooks;
  497. hook_result_copy_construction(this, o);
  498. }
  499. /*! AWAITING HUGO JSON CONVERSION TOOL
  500. SIGNATURE NOT RECOGNISED
  501. */
  502. BOOST_OUTCOME_TEMPLATE(class T)
  503. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, void, void>))
  504. constexpr basic_result(const success_type<T> &o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
  505. : base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(o)}
  506. {
  507. using namespace hooks;
  508. hook_result_copy_construction(this, o);
  509. }
  510. /*! AWAITING HUGO JSON CONVERSION TOOL
  511. SIGNATURE NOT RECOGNISED
  512. */
  513. BOOST_OUTCOME_TEMPLATE(class T)
  514. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void>))
  515. constexpr basic_result(success_type<T> &&o) noexcept(std::is_nothrow_constructible<value_type, T>::value) // NOLINT
  516. : base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
  517. {
  518. using namespace hooks;
  519. hook_result_move_construction(this, static_cast<success_type<T> &&>(o));
  520. }
  521. /*! AWAITING HUGO JSON CONVERSION TOOL
  522. SIGNATURE NOT RECOGNISED
  523. */
  524. BOOST_OUTCOME_TEMPLATE(class T)
  525. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
  526. constexpr basic_result(const failure_type<T> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
  527. : base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(o)}
  528. {
  529. using namespace hooks;
  530. hook_result_copy_construction(this, o);
  531. }
  532. /*! AWAITING HUGO JSON CONVERSION TOOL
  533. SIGNATURE NOT RECOGNISED
  534. */
  535. BOOST_OUTCOME_TEMPLATE(class T)
  536. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
  537. constexpr basic_result(failure_type<T> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(std::is_nothrow_constructible<error_type, T>::value) // NOLINT
  538. : base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
  539. {
  540. using namespace hooks;
  541. hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
  542. }
  543. /*! AWAITING HUGO JSON CONVERSION TOOL
  544. SIGNATURE NOT RECOGNISED
  545. */
  546. BOOST_OUTCOME_TEMPLATE(class T)
  547. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
  548. constexpr basic_result(const failure_type<T> &o, explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ = explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
  549. : base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
  550. {
  551. using namespace hooks;
  552. hook_result_copy_construction(this, o);
  553. }
  554. /*! AWAITING HUGO JSON CONVERSION TOOL
  555. SIGNATURE NOT RECOGNISED
  556. */
  557. BOOST_OUTCOME_TEMPLATE(class T)
  558. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
  559. constexpr basic_result(failure_type<T> &&o, explicit_make_error_code_compatible_move_conversion_tag /*unused*/ = explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
  560. : base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
  561. {
  562. using namespace hooks;
  563. hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
  564. }
  565. /*! AWAITING HUGO JSON CONVERSION TOOL
  566. SIGNATURE NOT RECOGNISED
  567. */
  568. BOOST_OUTCOME_TEMPLATE(class T)
  569. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
  570. constexpr basic_result(const failure_type<T> &o, explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ = explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
  571. : base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(o))}
  572. {
  573. using namespace hooks;
  574. hook_result_copy_construction(this, o);
  575. }
  576. /*! AWAITING HUGO JSON CONVERSION TOOL
  577. SIGNATURE NOT RECOGNISED
  578. */
  579. BOOST_OUTCOME_TEMPLATE(class T)
  580. BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
  581. constexpr basic_result(failure_type<T> &&o, explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ = explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
  582. : base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
  583. {
  584. using namespace hooks;
  585. hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
  586. }
  587. /*! AWAITING HUGO JSON CONVERSION TOOL
  588. SIGNATURE NOT RECOGNISED
  589. */
  590. constexpr void swap(basic_result &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
  591. && (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value))
  592. {
  593. constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
  594. constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
  595. detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
  596. }
  597. /*! AWAITING HUGO JSON CONVERSION TOOL
  598. SIGNATURE NOT RECOGNISED
  599. */
  600. auto as_failure() const & {
  601. return failure(this->assume_error()); }
  602. /*! AWAITING HUGO JSON CONVERSION TOOL
  603. SIGNATURE NOT RECOGNISED
  604. */
  605. auto as_failure() && {
  606. return failure(static_cast<basic_result &&>(*this).assume_error()); }
  607. };
  608. /*! AWAITING HUGO JSON CONVERSION TOOL
  609. SIGNATURE NOT RECOGNISED
  610. */
  611. template <class R, class S, class P> inline void swap(basic_result<R, S, P> &a, basic_result<R, S, P> &b) noexcept(noexcept(a.swap(b)))
  612. {
  613. a.swap(b);
  614. }
  615. #if !defined(NDEBUG)
  616. // Check is trivial in all ways except default constructibility
  617. // static_assert(std::is_trivial<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivial!");
  618. // static_assert(std::is_trivially_default_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially default constructible!");
  619. static_assert(std::is_trivially_copyable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copyable!");
  620. static_assert(std::is_trivially_assignable<basic_result<int, long, policy::all_narrow>, basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially assignable!");
  621. static_assert(std::is_trivially_destructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially destructible!");
  622. static_assert(std::is_trivially_copy_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy constructible!");
  623. static_assert(std::is_trivially_move_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move constructible!");
  624. static_assert(std::is_trivially_copy_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy assignable!");
  625. static_assert(std::is_trivially_move_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move assignable!");
  626. // Also check is standard layout
  627. static_assert(std::is_standard_layout<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not a standard layout type!");
  628. #endif
  629. BOOST_OUTCOME_V2_NAMESPACE_END
  630. #ifdef __clang__
  631. #pragma clang diagnostic pop
  632. #endif
  633. #endif