1 /* A very simple result type
2 (C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
3 File Created: June 2017
4
5
6 Boost Software License - Version 1.0 - August 17th, 2003
7
8 Permission is hereby granted, free of charge, to any person or organization
9 obtaining a copy of the software and accompanying documentation covered by
10 this license (the "Software") to use, reproduce, display, distribute,
11 execute, and transmit the Software, and to prepare derivative works of the
12 Software, and to permit third-parties to whom the Software is furnished to
13 do so, all subject to the following:
14
15 The copyright notices in the Software and this entire statement, including
16 the above license grant, this restriction and the following disclaimer,
17 must be included in all copies of the Software, in whole or in part, and
18 all derivative works of the Software, unless such copies or derivative
19 works are solely in the form of machine-executable object code generated by
20 a source language processor.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 */
30
31 #ifndef BOOST_OUTCOME_BASIC_RESULT_HPP
32 #define BOOST_OUTCOME_BASIC_RESULT_HPP
33
34 #include "config.hpp"
35 #include "convert.hpp"
36 #include "detail/basic_result_final.hpp"
37
38 #include "policy/all_narrow.hpp"
39 #include "policy/terminate.hpp"
40
41 #ifdef __clang__
42 #pragma clang diagnostic push
43 #pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
44 #endif
45
46 BOOST_OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
47
48 template <class R, class S, class NoValuePolicy> //
49 class basic_result;
50
51 namespace detail
52 {
53 // These are reused by basic_outcome to save load on the compiler
54 template <class value_type, class error_type> struct result_predicates
55 {
56 // Predicate for the implicit constructors to be available. Weakened to allow result<int, C enum>.
57 static constexpr bool implicit_constructors_enabled = //
58 !(trait::is_error_type<std::decay_t<value_type>>::value &&
59 trait::is_error_type<std::decay_t<error_type>>::value) // both value and error types are not whitelisted error types
60 && ((!detail::is_implicitly_constructible<value_type, error_type> &&
61 !detail::is_implicitly_constructible<error_type, value_type>) // if value and error types cannot be constructed into one another
62 || (trait::is_error_type<std::decay_t<error_type>>::value // if error type is a whitelisted error type
63 && !detail::is_implicitly_constructible<error_type, value_type> // AND which cannot be constructed from the value type
64 && std::is_integral<value_type>::value)); // AND the value type is some integral type
65
66 // Predicate for the value converting constructor to be available. Weakened to allow result<int, C enum>.
67 template <class T>
68 static constexpr bool enable_value_converting_constructor = //
69 implicit_constructors_enabled //
70 && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
71 && !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
72 && ((detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T>) // is unambiguously for value type
73 || (std::is_same<value_type, std::decay_t<T>>::value // OR is my value type exactly
74 && detail::is_implicitly_constructible<value_type, T>) ); // and my value type is constructible from this ref form of T
75
76
77 // Predicate for the error converting constructor to be available. Weakened to allow result<int, C enum>.
78 template <class T>
79 static constexpr bool enable_error_converting_constructor = //
80 implicit_constructors_enabled //
81 && !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
82 && !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
83 && ((!detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T>) // is unambiguously for error type
84 || (std::is_same<error_type, std::decay_t<T>>::value // OR is my error type exactly
85 && detail::is_implicitly_constructible<error_type, T>) ); // and my error type is constructible from this ref form of T
86
87 // Predicate for the error condition converting constructor to be available.
88 template <class ErrorCondEnum>
89 static constexpr bool enable_error_condition_converting_constructor = //
90 !is_in_place_type_t<std::decay_t<ErrorCondEnum>>::value // not in place construction
91 && trait::is_error_type_enum<error_type, std::decay_t<ErrorCondEnum>>::value // is an error condition enum
92 /*&& !detail::is_implicitly_constructible<value_type, ErrorCondEnum> && !detail::is_implicitly_constructible<error_type, ErrorCondEnum>*/; // not
93 // constructible
94 // via any other
95 // means
96
97 // Predicate for the converting constructor from a compatible input to be available.
98 template <class T, class U, class V>
99 static constexpr bool enable_compatible_conversion = //
100 (std::is_void<T>::value ||
101 detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // if our value types are constructible
102 &&(std::is_void<U>::value ||
103 detail::is_explicitly_constructible<error_type, typename basic_result<T, U, V>::error_type>) // if our error types are constructible
104 ;
105
106 // Predicate for the converting constructor from a make_error_code() of the input to be available.
107 template <class T, class U, class V>
108 static constexpr bool enable_make_error_code_compatible_conversion = //
109 trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
110 && !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
111 && (std::is_void<T>::value ||
112 detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
113 &&detail::is_explicitly_constructible<error_type,
114 typename trait::is_error_code_available<U>::type>; // and our error type is constructible from a make_error_code()
115
116 // Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
117 template <class T, class U, class V>
118 static constexpr bool enable_make_exception_ptr_compatible_conversion = //
119 trait::is_exception_ptr_available<std::decay_t<error_type>>::value // if error type has an exception ptr
120 && !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
121 && (std::is_void<T>::value ||
122 detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
123 &&detail::is_explicitly_constructible<error_type, typename trait::is_exception_ptr_available<U>::type>; // and our error type is constructible from a
124 // make_exception_ptr()
125
126 // Predicate for the implicit converting inplace constructor from a compatible input to be available.
127 struct disable_inplace_value_error_constructor;
128 template <class... Args>
129 using choose_inplace_value_error_constructor = std::conditional_t< //
130 detail::is_constructible<value_type, Args...> && detail::is_constructible<error_type, Args...>, //
131 disable_inplace_value_error_constructor, //
132 std::conditional_t< //
133 detail::is_constructible<value_type, Args...>, //
134 value_type, //
135 std::conditional_t< //
136 detail::is_constructible<error_type, Args...>, //
137 error_type, //
138 disable_inplace_value_error_constructor>>>;
139 template <class... Args>
140 static constexpr bool enable_inplace_value_error_constructor =
141 implicit_constructors_enabled //
142 && !std::is_same<choose_inplace_value_error_constructor<Args...>, disable_inplace_value_error_constructor>::value;
143 };
144
extract_value_from_success(const success_type<U> & v)145 template <class T, class U> constexpr inline const U &extract_value_from_success(const success_type<U> &v) { return v.value(); }
extract_value_from_success(success_type<U> && v)146 template <class T, class U> constexpr inline U &&extract_value_from_success(success_type<U> &&v) { return static_cast<success_type<U> &&>(v).value(); }
extract_value_from_success(const success_type<void> &)147 template <class T> constexpr inline T extract_value_from_success(const success_type<void> & /*unused*/) { return T{}; }
148
extract_error_from_failure(const failure_type<U,V> & v)149 template <class T, class U, class V> constexpr inline const U &extract_error_from_failure(const failure_type<U, V> &v) { return v.error(); }
extract_error_from_failure(failure_type<U,V> && v)150 template <class T, class U, class V> constexpr inline U &&extract_error_from_failure(failure_type<U, V> &&v)
151 {
152 return static_cast<failure_type<U, V> &&>(v).error();
153 }
extract_error_from_failure(const failure_type<void,V> &)154 template <class T, class V> constexpr inline T extract_error_from_failure(const failure_type<void, V> & /*unused*/) { return T{}; }
155
156 template <class T> struct is_basic_result
157 {
158 static constexpr bool value = false;
159 };
160 template <class R, class S, class T> struct is_basic_result<basic_result<R, S, T>>
161 {
162 static constexpr bool value = true;
163 };
164 } // namespace detail
165
166 /*! AWAITING HUGO JSON CONVERSION TOOL
167 type alias template <class T> is_basic_result. Potential doc page: `is_basic_result<T>`
168 */
169 template <class T> using is_basic_result = detail::is_basic_result<std::decay_t<T>>;
170 /*! AWAITING HUGO JSON CONVERSION TOOL
171 SIGNATURE NOT RECOGNISED
172 */
173 template <class T> static constexpr bool is_basic_result_v = detail::is_basic_result<std::decay_t<T>>::value;
174
175 namespace concepts
176 {
177 #if defined(__cpp_concepts)
178 /* The `basic_result` concept.
179 \requires That `U` matches a `basic_result`.
180 */
181 template <class U>
182 concept BOOST_OUTCOME_GCC6_CONCEPT_BOOL basic_result =
183 BOOST_OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
184 (requires(U v) { BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>(v); } && //
185 detail::convertible<U, BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>> && //
186 detail::base_of<BOOST_OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>, U>);
187 #else
188 namespace detail
189 {
190 inline no_match match_basic_result(...);
191 template <class R, class S, class NVP, class T, //
192 typename = typename T::value_type, //
193 typename = typename T::error_type, //
194 typename = typename T::no_value_policy_type, //
195 typename std::enable_if_t<std::is_convertible<T, BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>>::value && //
196 std::is_base_of<BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>, T>::value,
197 bool> = true>
198 inline BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> match_basic_result(BOOST_OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> &&, T &&);
199
200 template <class U>
201 static constexpr bool basic_result = BOOST_OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
202 !std::is_same<no_match, decltype(match_basic_result(std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>(),
203 std::declval<BOOST_OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
204 } // namespace detail
205 /* The `basic_result` concept.
206 \requires That `U` matches a `basic_result`.
207 */
208 template <class U> static constexpr bool basic_result = detail::basic_result<U>;
209 #endif
210 } // namespace concepts
211
212 /*! AWAITING HUGO JSON CONVERSION TOOL
213 SIGNATURE NOT RECOGNISED
214 */
215 namespace hooks
216 {
217 /*! AWAITING HUGO JSON CONVERSION TOOL
218 SIGNATURE NOT RECOGNISED
219 */
hook_result_construction(T *,U &&)220 template <class T, class U> constexpr inline void hook_result_construction(T * /*unused*/, U && /*unused*/) noexcept {}
221 /*! AWAITING HUGO JSON CONVERSION TOOL
222 SIGNATURE NOT RECOGNISED
223 */
hook_result_copy_construction(T *,U &&)224 template <class T, class U> constexpr inline void hook_result_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
225 /*! AWAITING HUGO JSON CONVERSION TOOL
226 SIGNATURE NOT RECOGNISED
227 */
hook_result_move_construction(T *,U &&)228 template <class T, class U> constexpr inline void hook_result_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
229 /*! AWAITING HUGO JSON CONVERSION TOOL
230 SIGNATURE NOT RECOGNISED
231 */
232 template <class T, class U, class... Args>
hook_result_in_place_construction(T *,in_place_type_t<U>,Args &&...)233 constexpr inline void hook_result_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept
234 {
235 }
236
237 /*! AWAITING HUGO JSON CONVERSION TOOL
238 SIGNATURE NOT RECOGNISED
239 */
spare_storage(const detail::basic_result_storage<R,S,NoValuePolicy> * r)240 template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_storage<R, S, NoValuePolicy> *r) noexcept
241 {
242 return r->_state._status.spare_storage_value;
243 }
244 /*! AWAITING HUGO JSON CONVERSION TOOL
245 SIGNATURE NOT RECOGNISED
246 */
247 template <class R, class S, class NoValuePolicy>
set_spare_storage(detail::basic_result_storage<R,S,NoValuePolicy> * r,uint16_t v)248 constexpr inline void set_spare_storage(detail::basic_result_storage<R, S, NoValuePolicy> *r, uint16_t v) noexcept
249 {
250 r->_state._status.spare_storage_value = v;
251 }
252 } // namespace hooks
253
254 /*! AWAITING HUGO JSON CONVERSION TOOL
255 type definition template <class R, class S, class NoValuePolicy> basic_result. Potential doc page: `basic_result<T, E, NoValuePolicy>`
256 */
257 template <class R, class S, class NoValuePolicy> //
258 class BOOST_OUTCOME_NODISCARD basic_result : public detail::basic_result_final<R, S, NoValuePolicy>
259 {
260 static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
261 static_assert(trait::type_can_be_used_in_basic_result<S>, "The type S cannot be used in a basic_result");
262 static_assert(std::is_void<S>::value || std::is_default_constructible<S>::value, "The type S must be void or default constructible");
263
264 using base = detail::basic_result_final<R, S, NoValuePolicy>;
265
266 struct implicit_constructors_disabled_tag
267 {
268 };
269 struct value_converting_constructor_tag
270 {
271 };
272 struct error_converting_constructor_tag
273 {
274 };
275 struct error_condition_converting_constructor_tag
276 {
277 };
278 struct explicit_valueornone_converting_constructor_tag
279 {
280 };
281 struct explicit_valueorerror_converting_constructor_tag
282 {
283 };
284 struct explicit_compatible_copy_conversion_tag
285 {
286 };
287 struct explicit_compatible_move_conversion_tag
288 {
289 };
290 struct explicit_make_error_code_compatible_copy_conversion_tag
291 {
292 };
293 struct explicit_make_error_code_compatible_move_conversion_tag
294 {
295 };
296 struct explicit_make_exception_ptr_compatible_copy_conversion_tag
297 {
298 };
299 struct explicit_make_exception_ptr_compatible_move_conversion_tag
300 {
301 };
302
303 public:
304 using value_type = R;
305 using error_type = S;
306 using no_value_policy_type = NoValuePolicy;
307
308 using value_type_if_enabled = typename base::_value_type;
309 using error_type_if_enabled = typename base::_error_type;
310
311 template <class T, class U = S, class V = NoValuePolicy> using rebind = basic_result<T, U, V>;
312
313 protected:
314 // Requirement predicates for result.
315 struct predicate
316 {
317 using base = detail::result_predicates<value_type, error_type>;
318
319 // Predicate for any constructors to be available at all
320 static constexpr bool constructors_enabled = !std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value;
321
322 // Predicate for implicit constructors to be available at all
323 static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
324
325 // Predicate for the value converting constructor to be available.
326 template <class T>
327 static constexpr bool enable_value_converting_constructor = //
328 constructors_enabled //
329 && !std::is_same<std::decay_t<T>, basic_result>::value // not my type
330 && base::template enable_value_converting_constructor<T>;
331
332 // Predicate for the error converting constructor to be available.
333 template <class T>
334 static constexpr bool enable_error_converting_constructor = //
335 constructors_enabled //
336 && !std::is_same<std::decay_t<T>, basic_result>::value // not my type
337 && base::template enable_error_converting_constructor<T>;
338
339 // Predicate for the error condition converting constructor to be available.
340 template <class ErrorCondEnum>
341 static constexpr bool enable_error_condition_converting_constructor = //
342 constructors_enabled //
343 && !std::is_same<std::decay_t<ErrorCondEnum>, basic_result>::value // not my type
344 && base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
345
346 // Predicate for the converting constructor from a compatible input to be available.
347 template <class T, class U, class V>
348 static constexpr bool enable_compatible_conversion = //
349 constructors_enabled //
350 && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
351 && base::template enable_compatible_conversion<T, U, V>;
352
353 // Predicate for the converting constructor from a make_error_code() of the input to be available.
354 template <class T, class U, class V>
355 static constexpr bool enable_make_error_code_compatible_conversion = //
356 constructors_enabled //
357 && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
358 && base::template enable_make_error_code_compatible_conversion<T, U, V>;
359
360 // Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
361 template <class T, class U, class V>
362 static constexpr bool enable_make_exception_ptr_compatible_conversion = //
363 constructors_enabled //
364 && !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
365 && base::template enable_make_exception_ptr_compatible_conversion<T, U, V>;
366
367 // Predicate for the inplace construction of value to be available.
368 template <class... Args>
369 static constexpr bool enable_inplace_value_constructor = //
370 constructors_enabled //
371 && (std::is_void<value_type>::value //
372 || detail::is_constructible<value_type, Args...>);
373
374 // Predicate for the inplace construction of error to be available.
375 template <class... Args>
376 static constexpr bool enable_inplace_error_constructor = //
377 constructors_enabled //
378 && (std::is_void<error_type>::value //
379 || detail::is_constructible<error_type, Args...>);
380
381 // Predicate for the implicit converting inplace constructor to be available.
382 template <class... Args>
383 static constexpr bool enable_inplace_value_error_constructor = //
384 constructors_enabled //
385 &&base::template enable_inplace_value_error_constructor<Args...>;
386 template <class... Args> using choose_inplace_value_error_constructor = typename base::template choose_inplace_value_error_constructor<Args...>;
387 };
388
389 public:
390 /*! AWAITING HUGO JSON CONVERSION TOOL
391 SIGNATURE NOT RECOGNISED
392 */
393 basic_result() = delete;
394 /*! AWAITING HUGO JSON CONVERSION TOOL
395 SIGNATURE NOT RECOGNISED
396 */
397 basic_result(basic_result && /*unused*/) = default; // NOLINT
398 /*! AWAITING HUGO JSON CONVERSION TOOL
399 SIGNATURE NOT RECOGNISED
400 */
401 basic_result(const basic_result & /*unused*/) = default;
402 /*! AWAITING HUGO JSON CONVERSION TOOL
403 SIGNATURE NOT RECOGNISED
404 */
405 basic_result &operator=(basic_result && /*unused*/) = default; // NOLINT
406 /*! AWAITING HUGO JSON CONVERSION TOOL
407 SIGNATURE NOT RECOGNISED
408 */
409 basic_result &operator=(const basic_result & /*unused*/) = default;
410 ~basic_result() = default;
411
412 /*! AWAITING HUGO JSON CONVERSION TOOL
413 SIGNATURE NOT RECOGNISED
414 */
415 BOOST_OUTCOME_TEMPLATE(class Arg, class... Args)
416 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!predicate::constructors_enabled && (sizeof...(Args) >= 0)))
417 basic_result(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_result<T, T> is NOT SUPPORTED, see docs!
418
419 /*! AWAITING HUGO JSON CONVERSION TOOL
420 SIGNATURE NOT RECOGNISED
421 */
422 BOOST_OUTCOME_TEMPLATE(class T)
423 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
424 && (detail::is_implicitly_constructible<value_type, T> || detail::is_implicitly_constructible<error_type, T>) )))
425 basic_result(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) =
426 delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
427
428 /*! AWAITING HUGO JSON CONVERSION TOOL
429 SIGNATURE NOT RECOGNISED
430 */
431 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_value_converting_constructor<T>))432 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
433 constexpr basic_result(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(
434 detail::is_nothrow_constructible<value_type, T>) // NOLINT
435 : base{in_place_type<typename base::value_type>, static_cast<T &&>(t)}
436 {
437 using namespace hooks;
438 hook_result_construction(this, static_cast<T &&>(t));
439 }
440 /*! AWAITING HUGO JSON CONVERSION TOOL
441 SIGNATURE NOT RECOGNISED
442 */
443 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_error_converting_constructor<T>))444 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
445 constexpr basic_result(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(
446 detail::is_nothrow_constructible<error_type, T>) // NOLINT
447 : base{in_place_type<typename base::error_type>, static_cast<T &&>(t)}
448 {
449 using namespace hooks;
450 hook_result_construction(this, static_cast<T &&>(t));
451 }
452 /*! AWAITING HUGO JSON CONVERSION TOOL
453 SIGNATURE NOT RECOGNISED
454 */
455 BOOST_OUTCOME_TEMPLATE(class ErrorCondEnum)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR (error_type (make_error_code (ErrorCondEnum ()))),BOOST_OUTCOME_TPRED (predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))456 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
457 BOOST_OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
458 constexpr basic_result(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(
459 noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
460 : base{in_place_type<typename base::error_type>, make_error_code(t)}
461 {
462 using namespace hooks;
463 hook_result_construction(this, static_cast<ErrorCondEnum &&>(t));
464 }
465
466 /*! AWAITING HUGO JSON CONVERSION TOOL
467 SIGNATURE NOT RECOGNISED
468 */
469 BOOST_OUTCOME_TEMPLATE(class T)
470 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(convert::value_or_error<basic_result, std::decay_t<T>>::enable_result_inputs || !concepts::basic_result<T>), //
471 BOOST_OUTCOME_TEXPR(convert::value_or_error<basic_result, std::decay_t<T>>{}(std::declval<T>())))
basic_result(T && o,explicit_valueorerror_converting_constructor_tag=explicit_valueorerror_converting_constructor_tag ())472 constexpr explicit basic_result(T &&o,
473 explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
474 : basic_result{convert::value_or_error<basic_result, std::decay_t<T>>{}(static_cast<T &&>(o))}
475 {
476 }
477 /*! AWAITING HUGO JSON CONVERSION TOOL
478 SIGNATURE NOT RECOGNISED
479 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)480 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
481 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
482 constexpr explicit basic_result(
483 const basic_result<T, U, V> &o,
484 explicit_compatible_copy_conversion_tag /*unused*/ =
485 explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
486 : base{typename base::compatible_conversion_tag(), o}
487 {
488 using namespace hooks;
489 hook_result_copy_construction(this, o);
490 }
491 /*! AWAITING HUGO JSON CONVERSION TOOL
492 SIGNATURE NOT RECOGNISED
493 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)494 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
495 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
496 constexpr explicit basic_result(
497 basic_result<T, U, V> &&o,
498 explicit_compatible_move_conversion_tag /*unused*/ =
499 explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
500 : base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
501 {
502 using namespace hooks;
503 hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
504 }
505 /*! AWAITING HUGO JSON CONVERSION TOOL
506 SIGNATURE NOT RECOGNISED
507 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)508 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
509 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
510 constexpr explicit basic_result(const basic_result<T, U, V> &o,
511 explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
512 explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
513 &&noexcept(make_error_code(std::declval<U>())))
514 : base{typename base::make_error_code_compatible_conversion_tag(), o}
515 {
516 using namespace hooks;
517 hook_result_copy_construction(this, o);
518 }
519 /*! AWAITING HUGO JSON CONVERSION TOOL
520 SIGNATURE NOT RECOGNISED
521 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)522 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
523 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
524 constexpr explicit basic_result(basic_result<T, U, V> &&o,
525 explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
526 explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
527 &&noexcept(make_error_code(std::declval<U>())))
528 : base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
529 {
530 using namespace hooks;
531 hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
532 }
533 /*! AWAITING HUGO JSON CONVERSION TOOL
534 SIGNATURE NOT RECOGNISED
535 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)536 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
537 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
538 constexpr explicit basic_result(const basic_result<T, U, V> &o,
539 explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
540 explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
541 &&noexcept(make_exception_ptr(std::declval<U>())))
542 : base{typename base::make_exception_ptr_compatible_conversion_tag(), o}
543 {
544 using namespace hooks;
545 hook_result_copy_construction(this, o);
546 }
547 /*! AWAITING HUGO JSON CONVERSION TOOL
548 SIGNATURE NOT RECOGNISED
549 */
BOOST_OUTCOME_TEMPLATE(class T,class U,class V)550 BOOST_OUTCOME_TEMPLATE(class T, class U, class V)
551 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
552 constexpr explicit basic_result(basic_result<T, U, V> &&o,
553 explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
554 explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
555 &&noexcept(make_exception_ptr(std::declval<U>())))
556 : base{typename base::make_exception_ptr_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
557 {
558 using namespace hooks;
559 hook_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
560 }
561
562 /*! AWAITING HUGO JSON CONVERSION TOOL
563 SIGNATURE NOT RECOGNISED
564 */
565 BOOST_OUTCOME_TEMPLATE(class... Args)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_inplace_value_constructor<Args...>))566 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
567 constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, Args...>)
568 : base{_, static_cast<Args &&>(args)...}
569 {
570 using namespace hooks;
571 hook_result_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
572 }
573 /*! AWAITING HUGO JSON CONVERSION TOOL
574 SIGNATURE NOT RECOGNISED
575 */
BOOST_OUTCOME_TEMPLATE(class U,class...Args)576 BOOST_OUTCOME_TEMPLATE(class U, class... Args)
577 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<std::initializer_list<U>, Args...>))
578 constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il,
579 Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>)
580 : base{_, il, static_cast<Args &&>(args)...}
581 {
582 using namespace hooks;
583 hook_result_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
584 }
585 /*! AWAITING HUGO JSON CONVERSION TOOL
586 SIGNATURE NOT RECOGNISED
587 */
588 BOOST_OUTCOME_TEMPLATE(class... Args)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_inplace_error_constructor<Args...>))589 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<Args...>))
590 constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, Args...>)
591 : base{_, static_cast<Args &&>(args)...}
592 {
593 using namespace hooks;
594 hook_result_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
595 }
596 /*! AWAITING HUGO JSON CONVERSION TOOL
597 SIGNATURE NOT RECOGNISED
598 */
BOOST_OUTCOME_TEMPLATE(class U,class...Args)599 BOOST_OUTCOME_TEMPLATE(class U, class... Args)
600 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<std::initializer_list<U>, Args...>))
601 constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il,
602 Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>)
603 : base{_, il, static_cast<Args &&>(args)...}
604 {
605 using namespace hooks;
606 hook_result_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
607 }
608 /*! AWAITING HUGO JSON CONVERSION TOOL
609 SIGNATURE NOT RECOGNISED
610 */
BOOST_OUTCOME_TEMPLATE(class A1,class A2,class...Args)611 BOOST_OUTCOME_TEMPLATE(class A1, class A2, class... Args)
612 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_inplace_value_error_constructor<A1, A2, Args...>))
613 constexpr basic_result(A1 &&a1, A2 &&a2, Args &&... args) noexcept(noexcept(
614 typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(), std::declval<Args>()...)))
615 : basic_result(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1),
616 static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
617 {
618 /* I was a little surprised that the below is needed given that we forward to another constructor.
619 But it turns out that ADL only fires on the first constructor for some reason.
620 */
621 using namespace hooks;
622 // hook_result_in_place_construction(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, this);
623 }
624
625 /*! AWAITING HUGO JSON CONVERSION TOOL
626 SIGNATURE NOT RECOGNISED
627 */
basic_result(const success_type<void> & o)628 constexpr basic_result(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
629 : base{in_place_type<value_type_if_enabled>}
630 {
631 using namespace hooks;
632 hook_result_copy_construction(this, o);
633 }
634 /*! AWAITING HUGO JSON CONVERSION TOOL
635 SIGNATURE NOT RECOGNISED
636 */
637 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_compatible_conversion<T,void,void>))638 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, void, void>))
639 constexpr basic_result(const success_type<T> &o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
640 : base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(o)}
641 {
642 using namespace hooks;
643 hook_result_copy_construction(this, o);
644 }
645 /*! AWAITING HUGO JSON CONVERSION TOOL
646 SIGNATURE NOT RECOGNISED
647 */
648 BOOST_OUTCOME_TEMPLATE(class T)
649 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void>))
basic_result(success_type<T> && o)650 constexpr basic_result(success_type<T> &&o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
651 : base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
652 {
653 using namespace hooks;
654 hook_result_move_construction(this, static_cast<success_type<T> &&>(o));
655 }
656 /*! AWAITING HUGO JSON CONVERSION TOOL
657 SIGNATURE NOT RECOGNISED
658 */
659 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_compatible_conversion<void,T,void>))660 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
661 constexpr basic_result(const failure_type<T> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(
662 detail::is_nothrow_constructible<error_type, T>) // NOLINT
663 : base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(o)}
664 {
665 using namespace hooks;
666 hook_result_copy_construction(this, o);
667 }
668 /*! AWAITING HUGO JSON CONVERSION TOOL
669 SIGNATURE NOT RECOGNISED
670 */
671 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_compatible_conversion<void,T,void>))672 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
673 constexpr basic_result(failure_type<T> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(
674 detail::is_nothrow_constructible<error_type, T>) // NOLINT
675 : base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
676 {
677 using namespace hooks;
678 hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
679 }
680 /*! AWAITING HUGO JSON CONVERSION TOOL
681 SIGNATURE NOT RECOGNISED
682 */
683 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_make_error_code_compatible_conversion<void,T,void>))684 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
685 constexpr basic_result(const failure_type<T> &o,
686 explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
687 explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
688 : base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
689 {
690 using namespace hooks;
691 hook_result_copy_construction(this, o);
692 }
693 /*! AWAITING HUGO JSON CONVERSION TOOL
694 SIGNATURE NOT RECOGNISED
695 */
696 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_make_error_code_compatible_conversion<void,T,void>))697 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
698 constexpr basic_result(failure_type<T> &&o,
699 explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
700 explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
701 : base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
702 {
703 using namespace hooks;
704 hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
705 }
706 /*! AWAITING HUGO JSON CONVERSION TOOL
707 SIGNATURE NOT RECOGNISED
708 */
709 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_make_exception_ptr_compatible_conversion<void,T,void>))710 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
711 constexpr basic_result(const failure_type<T> &o,
712 explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
713 explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
714 : base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(o))}
715 {
716 using namespace hooks;
717 hook_result_copy_construction(this, o);
718 }
719 /*! AWAITING HUGO JSON CONVERSION TOOL
720 SIGNATURE NOT RECOGNISED
721 */
722 BOOST_OUTCOME_TEMPLATE(class T)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (predicate::template enable_make_exception_ptr_compatible_conversion<void,T,void>))723 BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
724 constexpr basic_result(failure_type<T> &&o,
725 explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
726 explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
727 : base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
728 {
729 using namespace hooks;
730 hook_result_move_construction(this, static_cast<failure_type<T> &&>(o));
731 }
732
733 /*! AWAITING HUGO JSON CONVERSION TOOL
734 SIGNATURE NOT RECOGNISED
735 */
swap(basic_result & o)736 constexpr void swap(basic_result &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
737 && (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value))
738 {
739 constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
740 constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
741 detail::basic_result_storage_swap<value_throws, error_throws>(*this, o);
742 }
743
744 /*! AWAITING HUGO JSON CONVERSION TOOL
745 SIGNATURE NOT RECOGNISED
746 */
as_failure() const747 auto as_failure() const & { return failure(this->assume_error()); }
748 /*! AWAITING HUGO JSON CONVERSION TOOL
749 SIGNATURE NOT RECOGNISED
750 */
as_failure()751 auto as_failure() && { return failure(static_cast<basic_result &&>(*this).assume_error()); }
752
753 #ifdef __APPLE__
754 failure_type<error_type> _xcode_workaround_as_failure() &&;
755 #endif
756 };
757
758 /*! AWAITING HUGO JSON CONVERSION TOOL
759 SIGNATURE NOT RECOGNISED
760 */
swap(basic_result<R,S,P> & a,basic_result<R,S,P> & b)761 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)))
762 {
763 a.swap(b);
764 }
765
766 #if !defined(NDEBUG)
767 // Check is trivial in all ways except default constructibility
768 // static_assert(std::is_trivial<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivial!");
769 // static_assert(std::is_trivially_default_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially default
770 // constructible!");
771 static_assert(std::is_trivially_copyable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copyable!");
772 static_assert(std::is_trivially_assignable<basic_result<int, long, policy::all_narrow>, basic_result<int, long, policy::all_narrow>>::value,
773 "result<int> is not trivially assignable!");
774 static_assert(std::is_trivially_destructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially destructible!");
775 static_assert(std::is_trivially_copy_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy constructible!");
776 static_assert(std::is_trivially_move_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move constructible!");
777 static_assert(std::is_trivially_copy_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy assignable!");
778 static_assert(std::is_trivially_move_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move assignable!");
779 // Also check is standard layout
780 static_assert(std::is_standard_layout<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not a standard layout type!");
781 #endif
782
783 BOOST_OUTCOME_V2_NAMESPACE_END
784
785 #ifdef __clang__
786 #pragma clang diagnostic pop
787 #endif
788
789 #endif
790