sumty  0.1.0
Better sum types for C++
result.hpp
1 /* Copyright 2023 Jack A Bernard Jr.
2  *
3  * Licensed under the Apache License, Version 2.0 (the License);
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an AS IS BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef SUMTY_RESULT_HPP
17 #define SUMTY_RESULT_HPP
18 
19 #include "sumty/detail/fwd.hpp" // IWYU pragma: export
20 #include "sumty/detail/traits.hpp" // IWYU pragma: export
21 #include "sumty/detail/utils.hpp"
22 #include "sumty/exceptions.hpp"
23 #include "sumty/option.hpp" // IWYU pragma: keep
24 #include "sumty/utils.hpp" // IWYU pragma: export
25 #include "sumty/variant.hpp"
26 
27 #include <cstddef>
28 #include <functional>
29 #include <initializer_list>
30 #include <type_traits>
31 #include <utility>
32 
33 namespace sumty {
34 
35 /// @class result result.hpp <sumty/result.hpp>
36 /// @brief Type that contains an ok value, or an error.
37 ///
38 /// @details
39 /// @ref result is a reimplementation of `std::expected` with several
40 /// improvements. The key difference is that references (lvalue and rvalue) are
41 /// can be used for both the value type and the error type, and `void` can be
42 /// used for the error type (`std::expected` already allows `void` for the
43 /// value type).
44 ///
45 /// Internally, `result<T, E>` is represented as a @ref variant<T, E>. Thus,
46 /// @ref result benefits from the size optimizations implemented by @ref
47 /// variant (see @ref variant documentation for details). A couple special case
48 /// @ref result size examples are shown in the example below.
49 ///
50 /// ```
51 /// struct my_error {}; // NOTE: empty type
52 ///
53 /// assert(sizeof(result<void, my_error>) == sizeof(bool));
54 ///
55 /// assert(sizeof(result<int&, my_error>) == sizeof(int*));
56 /// ```
57 ///
58 /// In practice, the benefit of @ref result over `std::expected` is that @ref
59 /// result can be used in more places, especially with generic code. A generic
60 /// function (function template) that wants to be able to return a value of any
61 /// type, but also allow that return value to instead communicate an error on
62 /// failure can simply return a `result<T, E>`, where `T` is now allowed to be
63 /// a reference or even `void` (and so is `E`, for that matter).
64 ///
65 /// ```
66 /// struct negative_number_error {};
67 ///
68 /// // If value is negative, returns a negative_number_error. Otherwise,
69 /// // invokes func with the value as an argument and returns the result,
70 /// // even if the result is void or a reference.
71 /// template <typename F>
72 /// result<std::invoke_result_t<F>, negative_number_error>
73 /// call_if_non_negative(int value, F&& func) {
74 /// if (value < 0) {
75 /// return error<negative_number_error>();
76 /// }
77 /// // sumty::invoke needed to handle `void` return type
78 /// return invoke(std::forward<F>(func), value);
79 /// }
80 /// ```
81 ///
82 /// The power of @ref result is also enhanced when used in combination with
83 /// @ref error_set. @ref error_set makes it easy to represent a set of
84 /// different error possibilities of different types in a single value, and
85 /// simplifies error propagation when used with @ref result. See the
86 /// documentation of @ref error_set for more details and examples.
87 template <typename T, typename E>
88 class result : variant<T, E> {
89  private:
90  [[nodiscard]] constexpr variant<T, E>& res_() & noexcept {
91  return *static_cast<variant<T, E>*>(this);
92  }
93 
94  [[nodiscard]] constexpr const variant<T, E>& res_() const& noexcept {
95  return *static_cast<const variant<T, E>*>(this);
96  }
97 
98  [[nodiscard]] constexpr variant<T, E>&& res_() && {
99  return std::move(*static_cast<variant<T, E>*>(this));
100  }
101 
102  [[nodiscard]] constexpr const variant<T, E>& res_() const&& {
103  return std::move(*static_cast<const variant<T, E>*>(this));
104  }
105 
106  template <typename, typename>
107  friend class result;
108 
109  public:
110 #ifndef DOXYGEN
111  using value_type = typename detail::traits<T>::value_type;
112  using reference = typename detail::traits<T>::reference;
113  using const_reference = typename detail::traits<T>::const_reference;
114  using rvalue_reference = typename detail::traits<T>::rvalue_reference;
115  using const_rvalue_reference = typename detail::traits<T>::const_rvalue_reference;
116  using pointer = typename detail::traits<T>::pointer;
117  using const_pointer = typename detail::traits<T>::const_pointer;
118 
119  using error_type = typename detail::traits<E>::value_type;
120  using error_reference = typename detail::traits<E>::reference;
121  using error_const_reference = typename detail::traits<E>::const_reference;
122  using error_rvalue_reference = typename detail::traits<E>::rvalue_reference;
123  using error_const_rvalue_reference = typename detail::traits<E>::const_rvalue_reference;
124  using error_pointer = typename detail::traits<E>::pointer;
125  using error_const_pointer = typename detail::traits<E>::const_pointer;
126 #else
127  using value_type = ...;
128  using reference = ...;
129  using const_reference = ...;
130  using rvalue_reference = ...;
131  using const_rvalue_reference = ...;
132  using pointer = ...;
133  using const_pointer = ...;
134 
135  using error_type = ...;
136  using error_reference = ...;
137  using error_const_reference = ...;
138  using error_rvalue_reference = ...;
139  using error_const_rvalue_reference = ...;
140  using error_pointer = ...;
141  using error_const_pointer = ...;
142 #endif
143 
144  template <typename U>
145  using rebind = result<U, E>;
146 
147  template <typename V>
148  using rebind_error = result<T, V>;
149 
150  // For compatibility with std::expected
151  using unexpected_type = result<never, E>;
152 
153  /// @brief Default constructor
154  ///
155  /// @details
156  /// Initializes the @ref result with a default constructed ok value.
157  ///
158  /// ## Example
159  /// ```
160  /// result<int, std::string> res{};
161  ///
162  /// assert(res.has_value());
163  ///
164  /// assert(*res == 0);
165  /// ```
166  constexpr result()
167 #ifndef DOXYGEN
170  = default;
171 #else
172  CONDITIONALLY_NOEXCEPT;
173 #endif
174 
175  /// @brief Copy constructor
176  ///
177  /// @details
178  /// If the source @ref result has an ok value, the new @ref result is
179  /// initialized with a copy constructed ok value. If the source @ref result
180  /// has an error value, the new @ref result is initialized with a copy
181  /// constructed error.
182  ///
183  /// ## Example
184  /// ```
185  /// result<int, std::string> res1{42};
186  /// result<int, std::string> res2{in_place_error, "oh no"};
187  ///
188  /// result<int, std::string> res1_copy{res1};
189  /// result<int, std::string> res2_copy{res2};
190  ///
191  /// assert(res1_copy.has_value());
192  /// assert(*res1_copy == 42);
193  ///
194  /// assert(!res2_copy.has_value());
195  /// assert(res2_copy.error() == "oh no");
196  /// ```
197  constexpr result(const result&)
198 #ifndef DOXYGEN
200  requires(std::is_copy_constructible_v<variant<T, E>>)
201  = default;
202 #else
203  CONDITIONALLY_NOEXCEPT;
204 #endif
205 
206  /// @brief Move constructor
207  ///
208  /// @details
209  /// If the source @ref result has an ok value, the new @ref result is
210  /// initialized with a move constructed ok value. If the source @ref result
211  /// has an error value, the new @ref result is initialized with a move
212  /// constructed error.
213  ///
214  /// ## Example
215  /// ```
216  /// result<int, std::string> res1{42};
217  /// result<int, std::string> res2{in_place_error, "oh no"};
218  ///
219  /// result<int, std::string> res1_copy{std::move(res1)};
220  /// result<int, std::string> res2_copy{std::move(res2)};
221  ///
222  /// assert(res1_copy.has_value());
223  /// assert(*res1_copy == 42);
224  ///
225  /// assert(!res2_copy.has_value());
226  /// assert(res2_copy.error() == "oh no");
227  /// ```
228  constexpr result(result&&)
229 #ifndef DOXYGEN
231  requires(std::is_move_constructible_v<variant<T, E>>)
232  = default;
233 #else
234  CONDITIONALLY_NOEXCEPT;
235 #endif
236 
237  /// @brief Emplacement constructor
238  ///
239  /// @details
240  /// The @ref result is initialized such that an ok value is constructed in
241  /// place from the forwarded arguments.
242  ///
243  /// This constructor is `explicit` if `inplace` is the only argument.
244  ///
245  /// ## Example
246  /// ```
247  /// result<std::string, std::string> res{std::in_place, 5, 'a'};
248  ///
249  /// assert(res.has_value());
250  ///
251  /// assert(*res == "aaaaa");
252  /// ```
253  template <typename... Args>
254 #ifndef DOXYGEN
255  explicit(sizeof...(Args) == 0)
256 #else
258 #endif
259  // NOLINTNEXTLINE(hicpp-explicit-conversions)
260  constexpr result([[maybe_unused]] std::in_place_t inplace, Args&&... args)
261  : variant<T, E>(std::in_place_index<0>, std::forward<Args>(args)...) {
262  }
263 
264  /// @brief Emplacement constructor with initializer list
265  ///
266  /// @details
267  /// The @ref result is initialized such that an ok value is constructed in
268  /// place from the forwarded arguments.
269  ///
270  /// ## Example
271  /// ```
272  /// result<std::vector<int>, std::string> res{
273  /// std::in_place, {1, 2, 3, 4, 5}};
274  ///
275  /// assert(res.has_value());
276  ///
277  /// assert(res->size() == 5);
278  /// ```
279  template <typename U, typename... Args>
280  constexpr result([[maybe_unused]] std::in_place_t inplace,
281  std::initializer_list<U> init,
282  Args&&... args)
283  : variant<T, E>(std::in_place_index<0>, init, std::forward<Args>(args)...) {}
284 
285  /// @brief Emplacement constructor
286  ///
287  /// @details
288  /// The @ref result is initialized such that an ok value is constructed in
289  /// place from the forwarded arguments.
290  ///
291  /// This constructor is `explicit` if `inplace` is the only argument.
292  ///
293  /// ## Example
294  /// ```
295  /// result<std::string, std::string> res{std::in_place_index<0>, 5, 'a'};
296  ///
297  /// assert(res.has_value());
298  ///
299  /// assert(*res == "aaaaa");
300  /// ```
301  template <typename... Args>
302 #ifndef DOXYGEN
303  explicit(sizeof...(Args) == 0)
304 #else
306 #endif
307  // NOLINTNEXTLINE(hicpp-explicit-conversions)
308  constexpr result(std::in_place_index_t<0> inplace, Args&&... args)
309  : variant<T, E>(inplace, std::forward<Args>(args)...) {
310  }
311 
312  /// @brief Emplacement constructor with initializer list
313  ///
314  /// @details
315  /// The @ref result is initialized such that an ok value is constructed in
316  /// place from the forwarded arguments.
317  ///
318  /// ## Example
319  /// ```
320  /// result<std::vector<int>, std::string> res{
321  /// std::in_place_index<0>, {1, 2, 3, 4, 5}};
322  ///
323  /// assert(res.has_value());
324  ///
325  /// assert(res->size() == 5);
326  /// ```
327  template <typename U, typename... Args>
328  constexpr result(std::in_place_index_t<0> inplace,
329  std::initializer_list<U> init,
330  Args&&... args)
331  : variant<T, E>(inplace, init, std::forward<Args>(args)...) {}
332 
333  /// @brief Error emplacement constructor
334  ///
335  /// @details
336  /// The @ref result is initialized such that an error value is constructed
337  /// in place from the forwarded arguments.
338  ///
339  /// ## Example
340  /// ```
341  /// result<void, std::string> res{in_place_error, 5, 'a'};
342  ///
343  /// assert(!res.has_value());
344  ///
345  /// assert(res.error() == "aaaaa");
346  /// ```
347  template <typename... Args>
348 #ifndef DOXYGEN
349  explicit(sizeof...(Args) == 0)
350 #else
352 #endif
353  // NOLINTNEXTLINE(hicpp-explicit-conversions)
354  constexpr result(in_place_error_t inplace, Args&&... args)
355  : variant<T, E>(inplace, std::forward<Args>(args)...) {
356  }
357 
358  /// @brief Error emplacement constructor with initializer list
359  ///
360  /// @details
361  /// The @ref result is initialized such that an error value is constructed
362  /// in place from the forwarded arguments.
363  ///
364  /// ## Example
365  /// ```
366  /// result<void, std::vector<int>> res{in_place_error, {1, 2, 3, 4, 5}};
367  ///
368  /// assert(!res.has_value());
369  ///
370  /// assert(res.error().size() == 5);
371  /// ```
372  template <typename U, typename... Args>
373  constexpr result(in_place_error_t inplace,
374  std::initializer_list<U> init,
375  Args&&... args)
376  : variant<T, E>(inplace, init, std::forward<Args>(args)...) {}
377 
378  /// @brief Forwarding constructor
379  ///
380  /// @details
381  /// The @ref result is initialized such that it contains an ok value that
382  /// is constructed in place from the forwarded value.
383  ///
384  /// This constructor only participates in overload resolution if the ok
385  /// value is constructible from the forwarded value, the forwarded value is
386  /// not of type `std::in_place_t`, `sumty::in_place_t`,
387  /// `std::in_place_index_t<0>`, `sumty::in_place_index_t<0>`,
388  /// `std::in_place_index_t<1>`, `sumty::in_place_index_t<1>`, or
389  /// `sumty::in_place_error_t`, and either the ok value type is a scalar or
390  /// the forwarded value is not a @ref result instance.
391  ///
392  /// This constructor is `explicit` if the forwarded value is not implicitly
393  /// convertible to `T`.
394  ///
395  /// ## Example
396  /// ```
397  /// float value = 3.14;
398  ///
399  /// result<int, std::string> res{value};
400  ///
401  /// assert(res.has_value());
402  ///
403  /// assert(*res == 3);
404  /// ```
405  template <typename U>
406 #ifndef DOXYGEN
407  requires(std::is_constructible_v<variant<T, E>, std::in_place_index_t<0>, U &&> &&
413  explicit(!detail::traits<T>::template is_convertible_from<U>)
414 #else
416 #endif
417  // NOLINTNEXTLINE(hicpp-explicit-conversions)
418  constexpr result(U&& value)
419  : variant<T, E>(std::in_place_index<0>, std::forward<U>(value)) {
420  }
421 
422  /// @brief Converting copy constructor
423  ///
424  /// @details
425  /// This constructor converts a @ref result with one pair of ok and error
426  /// types into a @result of a different pair of ok and error types. This
427  /// constructor behaves much like the copy constructor, except that a type
428  /// conversion may occur.
429  ///
430  /// This constructor only particpates in overload resolution if the ok type
431  /// `T` of the destination @ref result is constructible from the ok type
432  /// `U` of the source @ref result, *and* the error type `E` of the
433  /// destiantion @ref result is constructible from the error type `V` of the
434  /// source @ref result.
435  ///
436  /// This constructor is `explicit` if either `U` or `V` is not implicitly
437  /// convertible to `T` or `E`, respectively.
438  ///
439  /// ## Example
440  /// ```
441  /// result<float, const char*> res1{3.14};
442  /// result<float, const char*> res2{in_place_error, "oh no"};
443  ///
444  /// result<int, std::string> res3{res1};
445  /// result<int, std::string> res4{res2};
446  ///
447  /// assert(res3.has_value());
448  /// assert(*res3 == 3);
449  ///
450  /// assert(!res4.has_value());
451  /// assert(res4.error() == "oh no");
452  /// ```
453  template <typename U, typename V>
454 #ifndef DOXYGEN
455  requires(((std::is_void_v<U> && detail::traits<T>::is_default_constructible) ||
457  std::in_place_index_t<0>,
458  typename detail::traits<U>::const_reference>) &&
461  std::in_place_index_t<1>,
462  typename detail::traits<E>::const_reference>))
463  explicit((!std::is_void_v<U> && !detail::traits<T>::template is_convertible_from<U>) ||
464  (!std::is_void_v<V> && !detail::traits<E>::template is_convertible_from<V>))
465 #else
467 #endif
468  // NOLINTNEXTLINE(hicpp-explicit-conversions)
469  constexpr result(const result<U, V>& other)
470  : variant<T, E>(detail::uninit) {
471  other.res_().visit_informed([this](auto&& value, auto info) {
472  res_().template uninit_emplace<info.index>(
473  std::forward<decltype(value)>(value));
474  });
475  }
476 
477  /// @brief Converting move constructor
478  ///
479  /// @details
480  /// This constructor converts a @ref result with one pair of ok and error
481  /// types into a @result of a different pair of ok and error types. This
482  /// constructor behaves much like the move constructor, except that a type
483  /// conversion may occur.
484  ///
485  /// This constructor only particpates in overload resolution if the ok type
486  /// `T` of the destination @ref result is constructible from the moved ok
487  /// type `U` of the source @ref result, *and* the error type `E` of the
488  /// destiantion @ref result is constructible from the move error type `V`
489  /// of the source @ref result.
490  ///
491  /// This constructor is `explicit` if either `U` or `V` is not implicitly
492  /// convertible to `T` or `E`, respectively.
493  ///
494  /// ## Example
495  /// ```
496  /// result<float, const char*> res1{3.14};
497  /// result<float, const char*> res2{in_place_error, "oh no"};
498  ///
499  /// result<int, std::string> res3{std::move(res1)};
500  /// result<int, std::string> res4{std::move(res2)};
501  ///
502  /// assert(res3.has_value());
503  /// assert(*res3 == 3);
504  ///
505  /// assert(!res4.has_value());
506  /// assert(res4.error() == "oh no");
507  /// ```
508  template <typename U, typename V>
509 #ifndef DOXYGEN
510  requires(((std::is_void_v<U> && detail::traits<T>::is_default_constructible) ||
512  std::in_place_index_t<0>,
513  typename detail::traits<U>::rvalue_reference>) &&
516  std::in_place_index_t<1>,
517  typename detail::traits<E>::rvalue_reference>))
518  explicit((!std::is_void_v<U> && !detail::traits<T>::template is_convertible_from<U>) ||
519  (!std::is_void_v<V> && !detail::traits<E>::template is_convertible_from<V>))
520 #else
522 #endif
523  // clang-format off
524  // NOLINTNEXTLINE(hicpp-explicit-conversions,cppcoreguidelines-rvalue-reference-param-not-moved)
525  constexpr result(result<U, V>&& other)
526  // clang-format on
527  : variant<T, E>(detail::uninit) {
528  std::move(other).res_().visit_informed([this](auto&& value, auto info) {
529  res_().template uninit_emplace<info.index>(
530  std::forward<decltype(value)>(value));
531  });
532  }
533 
534  /// @brief Destructor
535  ///
536  /// @details
537  /// Destroys the contained value in place.
538  ///
539  /// The desctructor is `noexcept` if both `T` and `E` are nothrow
540  /// destructible.
541  constexpr ~result()
542 #ifndef DOXYGEN
543  noexcept(std::is_nothrow_destructible_v<variant<T, E>>) = default;
544 #else
545  CONDITIONALLY_NOEXCEPT;
546 #endif
547 
548  /// @brief Copy assignment operator
549  ///
550  /// @details
551  /// The destination @ref result is reassigned such that it will now contain
552  /// a copy of the contained value of the source @ref result, which may be
553  /// either the ok type or the error type.
554  ///
555  /// If both the source and destination contain the ok type, or both contain
556  /// the error type, the values are copy assigned directly. Otherwise, the
557  /// old value in the destination is destroyed and the new value is copy
558  /// constructed.
559  ///
560  /// This function is `noexcept` if both `T` and `E` are all of the
561  /// following:
562  /// * Nothrow copy assignable
563  /// * Nothrow copy constructible
564  /// * Nothrow destructible
565  ///
566  /// ## Example
567  /// ```
568  /// result<float, const char*> res1{3.14};
569  /// result<float, const char*> res2{in_place_error, "oh no"};
570  ///
571  /// result<int, std::string> res3{};
572  /// result<int, std::string> res4{};
573  ///
574  /// res3 = res1;
575  /// res4 = res2;
576  ///
577  /// assert(res3.has_value());
578  /// assert(*res3 == 3);
579  ///
580  /// assert(!res4.has_value());
581  /// assert(res4.error() == "oh no");
582  /// ```
583  constexpr result& operator=(const result&)
584 #ifndef DOXYGEN
586  requires(std::is_copy_assignable_v<variant<T, E>>)
587  = default;
588 #else
589  CONDITIONALLY_NOEXCEPT;
590 #endif
591 
592  /// @brief Move assignment operator
593  ///
594  /// @details
595  /// The destination @ref result is reassigned such that it will now contain
596  /// the moved contained value of the source @ref result, which may be
597  /// either the ok type or the error type.
598  ///
599  /// If both the source and destination contain the ok type, or both contain
600  /// the error type, the values are move assigned directly. Otherwise, the
601  /// old value in the destination is destroyed and the new value is move
602  /// constructed.
603  ///
604  /// This function is `noexcept` if both `T` and `E` are all of the
605  /// following:
606  /// * Nothrow move assignable
607  /// * Nothrow move constructible
608  /// * Nothrow destructible
609  ///
610  /// ## Example
611  /// ```
612  /// result<float, const char*> res1{3.14};
613  /// result<float, const char*> res2{in_place_error, "oh no"};
614  ///
615  /// result<int, std::string> res3{};
616  /// result<int, std::string> res4{};
617  ///
618  /// res3 = std::move(res1);
619  /// res4 = std::move(res2);
620  ///
621  /// assert(res3.has_value());
622  /// assert(*res3 == 3);
623  ///
624  /// assert(!res4.has_value());
625  /// assert(res4.error() == "oh no");
626  /// ```
627  constexpr result& operator=(result&&)
628 #ifndef DOXYGEN
630  requires(std::is_move_assignable_v<variant<T, E>>)
631  = default;
632 #else
633  CONDITIONALLY_NOEXCEPT;
634 #endif
635 
636  /// @brief Value assignment operator
637  ///
638  /// @details
639  /// Sets the @ref result to contain the forwarded ok value, converted to
640  /// `T`. If the @ref result already contains an ok value, the forwarded
641  /// value is assigned directly to the contained value. Otherwise, the
642  /// error type is destroyed, and the ok type is constructed from the
643  /// forwarded value.
644  ///
645  /// This function only participates in overload resolution if:
646  /// * The source value is not a @ref result
647  /// * `T` is constructible from `U`
648  /// * `T` is assignable from `U`
649  ///
650  /// ## Example
651  /// ```
652  /// result<int, std::string> res{};
653  ///
654  /// res = 3.14;
655  ///
656  /// assert(res.has_value());
657  /// assert(*res == 3);
658  /// ```
659  template <typename U>
660 #ifndef DOXYGEN
661  requires(!std::is_same_v<result, std::remove_cvref_t<U>> &&
663  detail::traits<T>::template is_constructible<U> &&
664  detail::traits<T>::template is_assignable<U>)
665 #endif
666  constexpr result<T, E>& operator=(U&& value) {
667  if (res_().index() == 0) {
668  res_()[index<0>] = std::forward<U>(value);
669  } else {
670  res_().template emplace<0>(std::forward<U>(value));
671  }
672  return *this;
673  }
674 
675  /// @brief Implicit conversion to `bool`.
676  ///
677  /// @details
678  /// This implicit conversion allows a @ref result to be used directly in a
679  /// condition to check if the @ref result contains an ok value.
680  ///
681  /// ## Example
682  /// ```
683  /// result<int, std::string> res1{42};
684  /// result<int, std::string> res2 = error<std::string>("oh no");
685  ///
686  /// if (res1) {
687  /// assert(*res1 == 42);
688  /// } else {
689  /// assert(false);
690  /// }
691  ///
692  /// if (res2) {
693  /// assert(false);
694  /// } else {
695  /// assert(res2.error() == "oh no");
696  /// }
697  /// ```
698  // NOLINTNEXTLINE(hicpp-explicit-conversions)
699  constexpr operator bool() const noexcept { return res_().index() == 0; }
700 
701  /// @brief Returns `true` if the @ref result contains an ok value
702  ///
703  /// @details
704  /// ## Example
705  /// ```
706  /// result<int, std::string> res1{42};
707  /// result<int, std::string> res2{error<std::string>("oh no")};
708  ///
709  /// assert(res1.has_value());
710  /// assert(!res1.has_value());
711  /// ```
712  [[nodiscard]] constexpr bool has_value() const noexcept { return res_().index() == 0; }
713 
714  /// @brief Returns `true` if the @ref result contains an ok value
715  ///
716  /// @details
717  /// ## Example
718  /// ```
719  /// result<int, std::string> res1{42};
720  /// result<int, std::string> res2{error<std::string>("oh no")};
721  ///
722  /// assert(res1.is_ok());
723  /// assert(!res1.is_ok());
724  /// ```
725  [[nodiscard]] constexpr bool is_ok() const noexcept { return res_().index() == 0; }
726 
727  /// @brief Returns `true` if the @ref result contains an error value
728  ///
729  /// @details
730  /// ## Example
731  /// ```
732  /// result<int, std::string> res1{42};
733  /// result<int, std::string> res2{error<std::string>("oh no")};
734  ///
735  /// assert(!res1.is_error());
736  /// assert(res1.is_error());
737  /// ```
738  [[nodiscard]] constexpr bool is_error() const noexcept { return res_().index() != 0; }
739 
740  /// @brief Accesses the ok value contained in the @ref result
741  ///
742  /// @details
743  /// This operator does not check if the @ref result contains an ok value.
744  /// Use of this operator when the @ref result contains and error results in
745  /// undefined behavior.
746  ///
747  /// ## Example
748  /// ```
749  /// result<int, std::string> res{42};
750  ///
751  /// assert(*res == 42);
752  /// ```
753  [[nodiscard]] constexpr reference operator*() & noexcept { return res_()[index<0>]; }
754 
755  /// @brief Accesses the ok value contained in the @ref result
756  ///
757  /// @details
758  /// This operator does not check if the @ref result contains an ok value.
759  /// Use of this operator when the @ref result contains an error results in
760  /// undefined behavior.
761  ///
762  /// ## Example
763  /// ```
764  /// const result<int, std::string> res{42};
765  ///
766  /// assert(*res == 42);
767  /// ```
768  [[nodiscard]] constexpr const_reference operator*() const& noexcept {
769  return res_()[index<0>];
770  }
771 
772  /// @brief Accesses the ok value contained in the @ref result
773  ///
774  /// @details
775  /// This operator does not check if the @ref result contains an ok value.
776  /// Use of this operator when the @ref result contains an error results in
777  /// undefined behavior.
778  ///
779  /// ## Example
780  /// ```
781  /// result<int, std::string> res{42};
782  ///
783  /// assert(*std::move(res) == 42);
784  /// ```
785  [[nodiscard]] constexpr rvalue_reference operator*() && {
786  return std::move(*this).res_()[index<0>];
787  }
788 
789  /// @brief Accesses the ok value contained in the @ref result
790  ///
791  /// @details
792  /// This operator does not check if the @ref result contains an ok value.
793  /// Use of this operator when the @ref result contains an error results in
794  /// undefined behavior.
795  ///
796  /// ## Example
797  /// ```
798  /// const result<int, std::string> res{42};
799  ///
800  /// assert(*std::move(res) == 42);
801  /// ```
802  [[nodiscard]] constexpr const_rvalue_reference operator*() const&& {
803  return std::move(*this).res_()[index<0>];
804  }
805 
806  /// @brief Accesses members of the ok value contained in the @ref result
807  ///
808  /// @details
809  /// This operator does not check if the @ref result contains an ok value.
810  /// Use of this operator when the @ref result contains an error results in
811  /// undefined behavior.
812  ///
813  /// ## Example
814  /// ```
815  /// result<std::string, int> res{"hello"};
816  ///
817  /// assert(res->size() == 5);
818  /// ```
819  [[nodiscard]] constexpr pointer operator->() noexcept { return &res_()[index<0>]; }
820 
821  /// @brief Accesses members of the ok value contained in the @ref result
822  ///
823  /// @details
824  /// This operator does not check if the @ref result contains an ok value.
825  /// Use of this operator when the @ref result contains an error results in
826  /// undefined behavior.
827  ///
828  /// ## Example
829  /// ```
830  /// const result<std::string, int> res{"hello"};
831  ///
832  /// assert(res->size() == 5);
833  /// ```
834  [[nodiscard]] constexpr const_pointer operator->() const noexcept {
835  return &res_()[index<0>];
836  }
837 
838  /// @brief Accesses the ok value contained in the @ref result
839  ///
840  /// @details
841  /// This function first checks if the @ref result contains an ok value
842  /// before attempting to access the value. If the @ref result contains an
843  /// error, then this function throws an exception.
844  ///
845  /// ## Example
846  /// ```
847  /// result<int, std::string> res{42};
848  ///
849  /// assert(res.value() == 42);
850  /// ```
851  ///
852  /// @throws bad_result_access Thrown if the @ref result contains an error
853  [[nodiscard]] constexpr reference value() & {
854  if (res_().index() != 0) {
855  if constexpr (std::is_void_v<E>) {
856  throw bad_result_access<void>();
857  } else {
858  throw bad_result_access<std::remove_cvref_t<E>>(res_()[index<1>]);
859  }
860  }
861  return res_()[index<0>];
862  }
863 
864  /// @brief Accesses the ok value contained in the @ref result
865  ///
866  /// @details
867  /// This function first checks if the @ref result contains an ok value
868  /// before attempting to access the value. If the @ref result contains an
869  /// error, then this function throws an exception.
870  ///
871  /// ## Example
872  /// ```
873  /// const result<int, std::string> res{42};
874  ///
875  /// assert(res.value() == 42);
876  /// ```
877  ///
878  /// @throws bad_result_access Thrown if the @ref result contains an error
879  [[nodiscard]] constexpr const_reference value() const& {
880  if (res_().index() != 0) {
881  if constexpr (std::is_void_v<E>) {
882  throw bad_result_access<void>();
883  } else {
884  throw bad_result_access<std::remove_cvref_t<E>>(res_()[index<1>]);
885  }
886  }
887  return res_()[index<0>];
888  }
889 
890  /// @brief Accesses the ok value contained in the @ref result
891  ///
892  /// @details
893  /// This function first checks if the @ref result contains an ok value
894  /// before attempting to access the value. If the @ref result contains an
895  /// error, then this function throws an exception.
896  ///
897  /// ## Example
898  /// ```
899  /// result<int, std::string> res{42};
900  ///
901  /// assert(std::move(res).value() == 42);
902  /// ```
903  ///
904  /// @throws bad_result_access Thrown if the @ref result contains an error
905  [[nodiscard]] constexpr rvalue_reference value() && {
906  if (res_().index() != 0) {
907  if constexpr (std::is_void_v<E>) {
908  throw bad_result_access<void>();
909  } else {
910  throw bad_result_access<std::remove_cvref_t<E>>(
911  std::move(*this).res_()[index<1>]);
912  }
913  }
914  return std::move(*this).res_()[index<0>];
915  }
916 
917  /// @brief Accesses the ok value contained in the @ref result
918  ///
919  /// @details
920  /// This function first checks if the @ref result contains an ok value
921  /// before attempting to access the value. If the @ref result contains an
922  /// error, then this function throws an exception.
923  ///
924  /// ## Example
925  /// ```
926  /// const result<int, std::string> res{42};
927  ///
928  /// assert(std::move(res).value() == 42);
929  /// ```
930  ///
931  /// @throws bad_result_access Thrown if the @ref result contains an error
932  [[nodiscard]] constexpr rvalue_reference value() const&& {
933  if (res_().index() != 0) {
934  if constexpr (std::is_void_v<E>) {
935  throw bad_result_access<void>();
936  } else {
937  throw bad_result_access<std::remove_cvref_t<E>>(
938  std::move(*this).res_()[index<1>]);
939  }
940  }
941  return std::move(*this).res_()[index<0>];
942  }
943 
944  /// @brief Accesses the error value contained in the @ref result
945  ///
946  /// @details
947  /// This function does not check if the @ref result contains an ok value.
948  /// Use of this function when the @ref result contains an error results in
949  /// undefined behavior.
950  ///
951  /// ## Example
952  /// ```
953  /// result<int, std::string> res{in_place_error, "oh no"};
954  ///
955  /// assert(res.error() == "oh no");
956  /// ```
957  [[nodiscard]] constexpr error_reference error() & noexcept { return res_()[index<1>]; }
958 
959  /// @brief Accesses the error value contained in the @ref result
960  ///
961  /// @details
962  /// This function does not check if the @ref result contains an ok value.
963  /// Use of this function when the @ref result contains an error results in
964  /// undefined behavior.
965  ///
966  /// ## Example
967  /// ```
968  /// const result<int, std::string> res{in_place_error, "oh no"};
969  ///
970  /// assert(res.error() == "oh no");
971  /// ```
972  [[nodiscard]] constexpr error_const_reference error() const& noexcept {
973  return res_()[index<1>];
974  }
975 
976  /// @brief Accesses the error value contained in the @ref result
977  ///
978  /// @details
979  /// This function does not check if the @ref result contains an ok value.
980  /// Use of this function when the @ref result contains an error results in
981  /// undefined behavior.
982  ///
983  /// ## Example
984  /// ```
985  /// result<int, std::string> res{in_place_error, "oh no"};
986  ///
987  /// assert(std::move(res).error() == "oh no");
988  /// ```
989  [[nodiscard]] constexpr error_rvalue_reference error() && {
990  return std::move(*this).res_()[index<1>];
991  }
992 
993  /// @brief Accesses the error value contained in the @ref result
994  ///
995  /// @details
996  /// This function does not check if the @ref result contains an ok value.
997  /// Use of this function when the @ref result contains an error results in
998  /// undefined behavior.
999  ///
1000  /// ## Example
1001  /// ```
1002  /// const result<int, std::string> res{in_place_error, "oh no"};
1003  ///
1004  /// assert(std::move(res).error() == "oh no");
1005  /// ```
1006  [[nodiscard]] constexpr error_const_rvalue_reference error() const&& {
1007  return std::move(*this).res_()[index<1>];
1008  }
1009 
1010  /// @brief Extracts the error in order to propagate it
1011  ///
1012  /// @details
1013  /// This function returns the error value by itself. This
1014  /// value can then be converted into a different result type for the
1015  /// purpose of propagating the error.
1016  ///
1017  /// This function does not check if the @ref result contains an ok value.
1018  /// Use of this function when the @ref result contains an error results in
1019  /// undefined behavior.
1020  ///
1021  /// ## Example
1022  /// ```
1023  /// result<void, std::string> func() {
1024  /// result<int, std::string> res{in_place_error, "oh no"};
1025  ///
1026  /// return res.prop_error();
1027  /// }
1028  /// ```
1029  [[nodiscard]] constexpr result<never, E> prop_error() const& {
1030  return result<never, E>{in_place_error, error()};
1031  }
1032 
1033  /// @brief Extracts the error in order to propagate it
1034  ///
1035  /// @details
1036  /// This function returns the error value by itself. This
1037  /// value can then be converted into a different result type for the
1038  /// purpose of propagating the error.
1039  ///
1040  /// This function does not check if the @ref result contains an ok value.
1041  /// Use of this function when the @ref result contains an error results in
1042  /// undefined behavior.
1043  ///
1044  /// ## Example
1045  /// ```
1046  /// result<void, std::string> func() {
1047  /// result<int, std::string> res{in_place_error, "oh no"};
1048  ///
1049  /// return std::move(res).prop_error();
1050  /// }
1051  /// ```
1052  [[nodiscard]] constexpr result<never, E> prop_error() && {
1053  return result<never, E>{in_place_error, std::move(*this).error()};
1054  }
1055 
1056  /// @brief Gets the ok value, or a default if the @ref result is an error
1057  ///
1058  /// @details
1059  /// If the @ref result contains an ok value, a copy of that ok value is
1060  /// returned. If the @ref result contains an error value, the provided
1061  /// default value is forwarded, cast, and returned as by the following:
1062  /// `static_cast<T>(std::forward<U>(default_value))`.
1063  ///
1064  /// ## Example
1065  /// ```
1066  /// result<int, std::string> res1{42};
1067  /// result<int, std::string> res2{in_place_error, "oh no"};
1068  ///
1069  /// assert(res1.value_or(0) == 42);
1070  ///
1071  /// assert(res2.value_or(0) == 0);
1072  /// ```
1073  template <typename U>
1074  [[nodiscard]] constexpr value_type value_or(U&& default_value) const& {
1075  if (res_().index() == 0) {
1076  return res_()[index<0>];
1077  } else {
1078  return static_cast<value_type>(std::forward<U>(default_value));
1079  }
1080  }
1081 
1082  /// @brief Gets the ok value, or a default if the @ref result is an error
1083  ///
1084  /// @details
1085  /// If the @ref result contains an ok value, that ok value is
1086  /// returned. If the @ref result contains an error value, the provided
1087  /// default value is forwarded, cast, and returned as by the following:
1088  /// `static_cast<T>(std::forward<U>(default_value))`.
1089  ///
1090  /// ## Example
1091  /// ```
1092  /// result<int, std::string> res1{42};
1093  /// result<int, std::string> res2{in_place_error, "oh no"};
1094  ///
1095  /// assert(std::move(res1).value_or(0) == 42);
1096  ///
1097  /// assert(std::move(res2).value_or(0) == 0);
1098  /// ```
1099  template <typename U>
1100  [[nodiscard]] constexpr value_type value_or(U&& default_value) && {
1101  if (res_().index() == 0) {
1102  return std::move(*this).res_()[index<0>];
1103  } else {
1104  return static_cast<value_type>(std::forward<U>(default_value));
1105  }
1106  }
1107 
1108  /// @brief Gets the ok value, or returns the result of a callable
1109  ///
1110  /// @details
1111  /// If the @ref result contains an ok value, a copy of that ok value is
1112  /// returned. If the @ref result contains an error, the provided callable
1113  /// is invoked and the result is cast and returned, as if by:
1114  /// `static_cast<T>(std::invoke(std::forward<F>(f)))`.
1115  ///
1116  /// ## Example
1117  /// ```
1118  /// result<int, std::string> res1{42};
1119  /// result<int, std::string> res2{in_place_error, "oh no"};
1120  ///
1121  /// assert(res1.value_or_else([] { return 0; }) == 42);
1122  ///
1123  /// assert(res2.value_or_else({] { return 0; }) == 0);
1124  /// ```
1125  template <typename F>
1126  [[nodiscard]] constexpr value_type value_or_else(F&& f) const& {
1127  if (res_().index() == 0) {
1128  return res_()[index<0>];
1129  } else {
1130  return static_cast<T>(invoke(std::forward<F>(f)));
1131  }
1132  }
1133 
1134  /// @brief Gets the ok value, or returns the result of a callable
1135  ///
1136  /// @details
1137  /// If the @ref result contains an ok value, a copy of that ok value is
1138  /// returned. If the @ref result contains an error, the provided callable
1139  /// is invoked and the result is cast and returned, as if by:
1140  /// `static_cast<T>(std::invoke(std::forward<F>(f)))`.
1141  ///
1142  /// ## Example
1143  /// ```
1144  /// result<int, std::string> res1{42};
1145  /// result<int, std::string> res2{in_place_error, "oh no"};
1146  ///
1147  /// assert(std::move(res1).value_or_else([] { return 0; }) == 42);
1148  ///
1149  /// assert(std::move(res2).value_or_else({] { return 0; }) == 0);
1150  /// ```
1151  template <typename F>
1152  [[nodiscard]] constexpr value_type value_or_else(F&& f) && {
1153  if (res_().index() == 0) {
1154  return std::move(*this).res_()[index<0>];
1155  } else {
1156  return static_cast<T>(invoke(std::forward<F>(f)));
1157  }
1158  }
1159 
1160  /// @brief Accesses the ok value contained in the @ref result
1161  ///
1162  /// @details
1163  /// This function first checks if the @ref result contains an ok value
1164  /// before attempting to access the value. If the @ref result contains an
1165  /// error, then this function throws an exception.
1166  ///
1167  /// ## Example
1168  /// ```
1169  /// result<int, std::string> res{42};
1170  ///
1171  /// assert(res.ok() == 42);
1172  /// ```
1173  ///
1174  /// @throws bad_result_access Thrown if the @ref result contains an error
1175  [[nodiscard]] constexpr reference ok() & { return value(); }
1176 
1177  /// @brief Accesses the ok value contained in the @ref result
1178  ///
1179  /// @details
1180  /// This function first checks if the @ref result contains an ok value
1181  /// before attempting to access the value. If the @ref result contains an
1182  /// error, then this function throws an exception.
1183  ///
1184  /// ## Example
1185  /// ```
1186  /// const result<int, std::string> res{42};
1187  ///
1188  /// assert(res.ok() == 42);
1189  /// ```
1190  ///
1191  /// @throws bad_result_access Thrown if the @ref result contains an error
1192  [[nodiscard]] constexpr const_reference ok() const& { return value(); }
1193 
1194  /// @brief Accesses the ok value contained in the @ref result
1195  ///
1196  /// @details
1197  /// This function first checks if the @ref result contains an ok value
1198  /// before attempting to access the value. If the @ref result contains an
1199  /// error, then this function throws an exception.
1200  ///
1201  /// ## Example
1202  /// ```
1203  /// result<int, std::string> res{42};
1204  ///
1205  /// assert(std::move(res).ok() == 42);
1206  /// ```
1207  ///
1208  /// @throws bad_result_access Thrown if the @ref result contains an error
1209  [[nodiscard]] constexpr rvalue_reference ok() && { return std::move(*this).value(); }
1210 
1211  /// @brief Accesses the ok value contained in the @ref result
1212  ///
1213  /// @details
1214  /// This function first checks if the @ref result contains an ok value
1215  /// before attempting to access the value. If the @ref result contains an
1216  /// error, then this function throws an exception.
1217  ///
1218  /// ## Example
1219  /// ```
1220  /// const result<int, std::string> res{42};
1221  ///
1222  /// assert(std::move(res).ok() == 42);
1223  /// ```
1224  ///
1225  /// @throws bad_result_access Thrown if the @ref result contains an error
1226  [[nodiscard]] constexpr rvalue_reference ok() const&& {
1227  return std::move(*this).value();
1228  }
1229 
1230  /// @brief Gets the ok value, or a default if the @ref result is an error
1231  ///
1232  /// @details
1233  /// If the @ref result contains an ok value, a copy of that ok value is
1234  /// returned. If the @ref result contains an error value, the provided
1235  /// default value is forwarded, cast, and returned as by the following:
1236  /// `static_cast<T>(std::forward<U>(default_value))`.
1237  ///
1238  /// ## Example
1239  /// ```
1240  /// result<int, std::string> res1{42};
1241  /// result<int, std::string> res2{in_place_error, "oh no"};
1242  ///
1243  /// assert(res1.ok_or(0) == 42);
1244  ///
1245  /// assert(res2.ok_or(0) == 0);
1246  /// ```
1247  template <typename U>
1248  [[nodiscard]] constexpr value_type ok_or(U&& default_value) const& {
1249  return value_or(std::forward<U>(default_value));
1250  }
1251 
1252  /// @brief Gets the ok value, or a default if the @ref result is an error
1253  ///
1254  /// @details
1255  /// If the @ref result contains an ok value, that ok value is
1256  /// returned. If the @ref result contains an error value, the provided
1257  /// default value is forwarded, cast, and returned as by the following:
1258  /// `static_cast<T>(std::forward<U>(default_value))`.
1259  ///
1260  /// ## Example
1261  /// ```
1262  /// result<int, std::string> res1{42};
1263  /// result<int, std::string> res2{in_place_error, "oh no"};
1264  ///
1265  /// assert(std::move(res1).ok_or(0) == 42);
1266  ///
1267  /// assert(std::move(res2).ok_or(0) == 0);
1268  /// ```
1269  template <typename U>
1270  [[nodiscard]] constexpr value_type ok_or(U&& default_value) && {
1271  return std::move(*this).ok_or(std::forward<U>(default_value));
1272  }
1273 
1274  /// @brief Gets the ok value, or returns the result of a callable
1275  ///
1276  /// @details
1277  /// If the @ref result contains an ok value, a copy of that ok value is
1278  /// returned. If the @ref result contains an error, the provided callable
1279  /// is invoked and the result is cast and returned, as if by:
1280  /// `static_cast<T>(std::invoke(std::forward<F>(f)))`.
1281  ///
1282  /// ## Example
1283  /// ```
1284  /// result<int, std::string> res1{42};
1285  /// result<int, std::string> res2{in_place_error, "oh no"};
1286  ///
1287  /// assert(res1.ok_or_else([] { return 0; }) == 42);
1288  ///
1289  /// assert(res2.ok_or_else({] { return 0; }) == 0);
1290  /// ```
1291  template <typename F>
1292  [[nodiscard]] constexpr value_type ok_or_else(F&& f) const& {
1293  return value_or_else(std::forward<F>(f));
1294  }
1295 
1296  /// @brief Gets the ok value, or returns the result of a callable
1297  ///
1298  /// @details
1299  /// If the @ref result contains an ok value, a copy of that ok value is
1300  /// returned. If the @ref result contains an error, the provided callable
1301  /// is invoked and the result is cast and returned, as if by:
1302  /// `static_cast<T>(std::invoke(std::forward<F>(f)))`.
1303  ///
1304  /// ## Example
1305  /// ```
1306  /// result<int, std::string> res1{42};
1307  /// result<int, std::string> res2{in_place_error, "oh no"};
1308  ///
1309  /// assert(std::move(res1).ok_or_else([] { return 0; }) == 42);
1310  ///
1311  /// assert(std::move(res2).ok_or_else({] { return 0; }) == 0);
1312  /// ```
1313  template <typename F>
1314  [[nodiscard]] constexpr value_type ok_or_else(F&& f) && {
1315  return std::move(*this).value_or_else(std::forward<F>(f));
1316  }
1317 
1318  /// @brief Applies a callable to the contents of a @ref result
1319  ///
1320  /// @details
1321  /// If the @ref result contains an ok value, the value is passed into the
1322  /// callable, and the result of invoking the callable is returned from this
1323  /// function. If the @ref result contains an error, the callable is not
1324  /// invoked, and a copy of the error is returned.
1325  ///
1326  /// This function only participates in overload resultion if the result of
1327  /// invoking the callable is a @ref result.
1328  ///
1329  /// ## Example
1330  /// ```
1331  /// result<int, std::string> res1{42};
1332  /// result<int, std::string> res2{-42};
1333  /// result<int, std::string> res3{in_place_error, "oh no"};
1334  ///
1335  /// auto callable = [](int value) -> result<unsigned int, const char*> {
1336  /// if (value < 0) {
1337  /// return error<const char*>("negaive value");
1338  /// } else {
1339  /// return static_cast<unsigned int>(value);
1340  /// }
1341  /// };
1342  ///
1343  /// auto res1_new = res1.and_then(callable);
1344  /// auto res2_new = res2.and_then(callable);
1345  /// auto res3_new = res3.and_then(callable);
1346  ///
1347  /// assert(res1_new.is_ok());
1348  /// assert(*res1_new == 42);
1349  ///
1350  /// assert(res2_new.is_error());
1351  /// assert(res2_new.error() == "negative value");
1352  ///
1353  /// assert(res3_new.is_error());
1354  /// assert(res3_new.error() == "oh no");
1355  /// ```
1356  template <typename F>
1357  constexpr auto and_then(F&& f) &
1358 #ifndef DOXYGEN
1359  requires(
1361 #endif
1362  {
1363  if constexpr (std::is_void_v<T>) {
1364  if (res_().index() == 0) {
1365  return std::invoke(std::forward<F>(f), void_v);
1366  } else {
1367  if constexpr (std::is_void_v<E>) {
1368  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1369  in_place_error};
1370  } else {
1371  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1372  in_place_error, res_()[index<1>]};
1373  }
1374  }
1375  } else {
1376  if (res_().index() == 0) {
1377  return std::invoke(std::forward<F>(f), res_()[index<0>]);
1378  } else {
1379  if constexpr (std::is_void_v<E>) {
1380  return std::remove_cvref_t<std::invoke_result_t<F, reference>>{
1381  in_place_error};
1382  } else {
1383  return std::remove_cvref_t<std::invoke_result_t<F, reference>>{
1384  in_place_error, res_()[index<1>]};
1385  }
1386  }
1387  }
1388  }
1389 
1390  /// @brief Applies a callable to the contents of a @ref result
1391  ///
1392  /// @details
1393  /// If the @ref result contains an ok value, the value is passed into the
1394  /// callable, and the result of invoking the callable is returned from this
1395  /// function. If the @ref result contains an error, the callable is not
1396  /// invoked, and a copy of the error is returned.
1397  ///
1398  /// This function only participates in overload resultion if the result of
1399  /// invoking the callable is a @ref result.
1400  ///
1401  /// ## Example
1402  /// ```
1403  /// const result<int, std::string> res1{42};
1404  /// const result<int, std::string> res2{-42};
1405  /// const result<int, std::string> res3{in_place_error, "oh no"};
1406  ///
1407  /// auto callable = [](int value) -> result<unsigned int, const char*> {
1408  /// if (value < 0) {
1409  /// return error<const char*>("negaive value");
1410  /// } else {
1411  /// return static_cast<unsigned int>(value);
1412  /// }
1413  /// };
1414  ///
1415  /// auto res1_new = res1.and_then(callable);
1416  /// auto res2_new = res2.and_then(callable);
1417  /// auto res3_new = res3.and_then(callable);
1418  ///
1419  /// assert(res1_new.is_ok());
1420  /// assert(*res1_new == 42);
1421  ///
1422  /// assert(res2_new.is_error());
1423  /// assert(res2_new.error() == "negative value");
1424  ///
1425  /// assert(res3_new.is_error());
1426  /// assert(res3_new.error() == "oh no");
1427  /// ```
1428  template <typename F>
1429  constexpr auto and_then(F&& f) const& {
1430  if constexpr (std::is_void_v<T>) {
1431  if (res_().index() == 0) {
1432  return std::invoke(std::forward<F>(f), void_v);
1433  } else {
1434  if constexpr (std::is_void_v<E>) {
1435  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1436  in_place_error};
1437  } else {
1438  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1439  in_place_error, res_()[index<1>]};
1440  }
1441  }
1442  } else {
1443  if (res_().index() == 0) {
1444  return std::invoke(std::forward<F>(f), res_()[index<0>]);
1445  } else {
1446  if constexpr (std::is_void_v<E>) {
1447  return std::remove_cvref_t<std::invoke_result_t<F, const_reference>>{
1448  in_place_error};
1449  } else {
1450  return std::remove_cvref_t<std::invoke_result_t<F, const_reference>>{
1451  in_place_error, res_()[index<1>]};
1452  }
1453  }
1454  }
1455  }
1456 
1457  /// @brief Applies a callable to the contents of a @ref result
1458  ///
1459  /// @details
1460  /// If the @ref result contains an ok value, the value is passed into the
1461  /// callable, and the result of invoking the callable is returned from this
1462  /// function. If the @ref result contains an error, the callable is not
1463  /// invoked, the error is returned.
1464  ///
1465  /// This function only participates in overload resultion if the result of
1466  /// invoking the callable is a @ref result.
1467  ///
1468  /// ## Example
1469  /// ```
1470  /// result<int, std::string> res1{42};
1471  /// result<int, std::string> res2{-42};
1472  /// result<int, std::string> res3{in_place_error, "oh no"};
1473  ///
1474  /// auto callable = [](int value) -> result<unsigned int, const char*> {
1475  /// if (value < 0) {
1476  /// return error<const char*>("negaive value");
1477  /// } else {
1478  /// return static_cast<unsigned int>(value);
1479  /// }
1480  /// };
1481  ///
1482  /// auto res1_new = std::move(res1).and_then(callable);
1483  /// auto res2_new = std::move(res2).and_then(callable);
1484  /// auto res3_new = std::move(res3).and_then(callable);
1485  ///
1486  /// assert(res1_new.is_ok());
1487  /// assert(*res1_new == 42);
1488  ///
1489  /// assert(res2_new.is_error());
1490  /// assert(res2_new.error() == "negative value");
1491  ///
1492  /// assert(res3_new.is_error());
1493  /// assert(res3_new.error() == "oh no");
1494  /// ```
1495  template <typename F>
1496  constexpr auto and_then(F&& f) && {
1497  if constexpr (std::is_void_v<T>) {
1498  if (res_().index() == 0) {
1499  return std::invoke(std::forward<F>(f), void_v);
1500  } else {
1501  if constexpr (std::is_void_v<E>) {
1502  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1503  in_place_error};
1504  } else {
1505  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1506  in_place_error, std::move(*this).res_()[index<1>]};
1507  }
1508  }
1509  } else {
1510  if (res_().index() == 0) {
1511  return std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>]);
1512  } else {
1513  if constexpr (std::is_void_v<E>) {
1514  return std::remove_cvref_t<std::invoke_result_t<F, rvalue_reference>>{
1515  in_place_error};
1516  } else {
1517  return std::remove_cvref_t<std::invoke_result_t<F, rvalue_reference>>{
1518  in_place_error, std::move(*this).res_()[index<1>]};
1519  }
1520  }
1521  }
1522  }
1523 
1524  /// @brief Applies a callable to the contents of a @ref result
1525  ///
1526  /// @details
1527  /// If the @ref result contains an ok value, the value is passed into the
1528  /// callable, and the result of invoking the callable is returned from this
1529  /// function. If the @ref result contains an error, the callable is not
1530  /// invoked, the error is returned.
1531  ///
1532  /// This function only participates in overload resultion if the result of
1533  /// invoking the callable is a @ref result.
1534  ///
1535  /// ## Example
1536  /// ```
1537  /// const result<int, std::string> res1{42};
1538  /// const result<int, std::string> res2{-42};
1539  /// const result<int, std::string> res3{in_place_error, "oh no"};
1540  ///
1541  /// auto callable = [](int value) -> result<unsigned int, const char*> {
1542  /// if (value < 0) {
1543  /// return error<const char*>("negaive value");
1544  /// } else {
1545  /// return static_cast<unsigned int>(value);
1546  /// }
1547  /// };
1548  ///
1549  /// auto res1_new = std::move(res1).and_then(callable);
1550  /// auto res2_new = std::move(res2).and_then(callable);
1551  /// auto res3_new = std::move(res3).and_then(callable);
1552  ///
1553  /// assert(res1_new.is_ok());
1554  /// assert(*res1_new == 42);
1555  ///
1556  /// assert(res2_new.is_error());
1557  /// assert(res2_new.error() == "negative value");
1558  ///
1559  /// assert(res3_new.is_error());
1560  /// assert(res3_new.error() == "oh no");
1561  /// ```
1562  template <typename F>
1563  constexpr auto and_then(F&& f) const&& {
1564  if constexpr (std::is_void_v<T>) {
1565  if (res_().index() == 0) {
1566  return std::invoke(std::forward<F>(f), void_v);
1567  } else {
1568  if constexpr (std::is_void_v<E>) {
1569  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1570  in_place_error};
1571  } else {
1572  return std::remove_cvref_t<std::invoke_result_t<F, void_t>>{
1573  in_place_error, std::move(*this).res_()[index<1>]};
1574  }
1575  }
1576  } else {
1577  if (res_().index() == 0) {
1578  return std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>]);
1579  } else {
1580  if constexpr (std::is_void_v<E>) {
1581  return std::remove_cvref_t<
1582  std::invoke_result_t<F, const_rvalue_reference>>{in_place_error};
1583  } else {
1584  return std::remove_cvref_t<
1585  std::invoke_result_t<F, const_rvalue_reference>>{
1586  in_place_error, std::move(*this).res_()[index<1>]};
1587  }
1588  }
1589  }
1590  }
1591 
1592  /// @brief Perforams a transformation on the ok value of a @ref result
1593  ///
1594  /// @details
1595  /// If the @ref result contains an ok value, that value is passed to the
1596  /// transformation callable provided. The value returned from the callable
1597  /// is then returned from this function as the ok value of a new @ref
1598  /// result, where ok type of the new result is the exact type returned
1599  /// from the callable. If the @ref result contains an error value, a copy
1600  /// of the error is returned.
1601  ///
1602  /// Note that this function is identical to @ref map, but the name
1603  /// `transform` makes @ref result able to be a drop in replacement for
1604  /// `std::expected`. `map` is the more typical name of this monadic
1605  /// operation outside of C++.
1606  ///
1607  /// ## Example
1608  /// ```
1609  /// result<int, std::string> res1{42};
1610  /// result<int, std::string> res2{in_place_error, "oh no"};
1611  ///
1612  /// auto res1_mapped = res1.transform([](auto value) {
1613  /// return std::to_string(value);
1614  /// });
1615  /// auto res2_mapped = res2.transform([](auto value) {
1616  /// return std::to_string(value);
1617  /// });
1618  ///
1619  /// assert(res1_mapped.is_error());
1620  /// assert(res1_mapped.error() == "oh no");
1621  ///
1622  /// assert(res2_mapped.is_ok());
1623  /// assert(*res2_mapped == "42");
1624  /// ```
1625  template <typename F>
1626  constexpr auto transform(F&& f) & {
1627  if constexpr (std::is_void_v<T>) {
1628  using res_t = std::invoke_result_t<F, void_t>;
1629  if (res_().index() == 0) {
1630  if constexpr (std::is_void_v<res_t>) {
1631  std::invoke(std::forward<F>(f), void_v);
1632  return result<res_t, E>{std::in_place};
1633  } else {
1634  return result<res_t, E>{std::in_place,
1635  std::invoke(std::forward<F>(f), void_v)};
1636  }
1637  } else {
1638  if constexpr (std::is_void_v<E>) {
1639  return result<res_t, E>{in_place_error};
1640  } else {
1641  return result<res_t, E>{in_place_error, res_()[index<1>]};
1642  }
1643  }
1644  } else {
1645  using res_t = std::invoke_result_t<F, reference>;
1646  if (res_().index() == 0) {
1647  if constexpr (std::is_void_v<res_t>) {
1648  std::invoke(std::forward<F>(f), res_()[index<0>]);
1649  return result<res_t, E>{std::in_place};
1650  } else {
1651  return result<res_t, E>{
1652  std::in_place, std::invoke(std::forward<F>(f), res_()[index<0>])};
1653  }
1654  } else {
1655  if constexpr (std::is_void_v<E>) {
1656  return result<res_t, E>{in_place_error};
1657  } else {
1658  return result<res_t, E>{in_place_error, res_()[index<1>]};
1659  }
1660  }
1661  }
1662  }
1663 
1664  /// @brief Perforams a transformation on the ok value of a @ref result
1665  ///
1666  /// @details
1667  /// If the @ref result contains an ok value, that value is passed to the
1668  /// transformation callable provided. The value returned from the callable
1669  /// is then returned from this function as the ok value of a new @ref
1670  /// result, where ok type of the new result is the exact type returned
1671  /// from the callable. If the @ref result contains an error value, a copy
1672  /// of the error is returned.
1673  ///
1674  /// Note that this function is identical to @ref map, but the name
1675  /// `transform` makes @ref result able to be a drop in replacement for
1676  /// `std::expected`. `map` is the more typical name of this monadic
1677  /// operation outside of C++.
1678  ///
1679  /// ## Example
1680  /// ```
1681  /// const result<int, std::string> res1{42};
1682  /// const result<int, std::string> res2{in_place_error, "oh no"};
1683  ///
1684  /// auto res1_mapped = res1.transform([](auto value) {
1685  /// return std::to_string(value);
1686  /// });
1687  /// auto res2_mapped = res2.transform([](auto value) {
1688  /// return std::to_string(value);
1689  /// });
1690  ///
1691  /// assert(res1_mapped.is_error());
1692  /// assert(res1_mapped.error() == "oh no");
1693  ///
1694  /// assert(res2_mapped.is_ok());
1695  /// assert(*res2_mapped == "42");
1696  /// ```
1697  template <typename F>
1698  constexpr auto transform(F&& f) const& {
1699  if constexpr (std::is_void_v<T>) {
1700  using res_t = std::invoke_result_t<F, void_t>;
1701  if (res_().index() == 0) {
1702  if constexpr (std::is_void_v<res_t>) {
1703  std::invoke(std::forward<F>(f), void_v);
1704  return result<res_t, E>{std::in_place};
1705  } else {
1706  return result<res_t, E>{std::in_place,
1707  std::invoke(std::forward<F>(f), void_v)};
1708  }
1709  } else {
1710  if constexpr (std::is_void_v<E>) {
1711  return result<res_t, E>{in_place_error};
1712  } else {
1713  return result<res_t, E>{in_place_error, res_()[index<1>]};
1714  }
1715  }
1716  } else {
1717  using res_t = std::invoke_result_t<F, const_reference>;
1718  if (res_().index() == 0) {
1719  if constexpr (std::is_void_v<res_t>) {
1720  std::invoke(std::forward<F>(f), res_()[index<0>]);
1721  return result<res_t, E>{std::in_place};
1722  } else {
1723  return result<res_t, E>{
1724  std::in_place, std::invoke(std::forward<F>(f), res_()[index<0>])};
1725  }
1726  } else {
1727  if constexpr (std::is_void_v<E>) {
1728  return result<res_t, E>{in_place_error};
1729  } else {
1730  return result<res_t, E>{in_place_error, res_()[index<1>]};
1731  }
1732  }
1733  }
1734  }
1735 
1736  /// @brief Perforams a transformation on the ok value of a @ref result
1737  ///
1738  /// @details
1739  /// If the @ref result contains an ok value, that value is passed to the
1740  /// transformation callable provided. The value returned from the callable
1741  /// is then returned from this function as the ok value of a new @ref
1742  /// result, where ok type of the new result is the exact type returned
1743  /// from the callable. If the @ref result contains an error value, the
1744  /// error is returned.
1745  ///
1746  /// Note that this function is identical to @ref map, but the name
1747  /// `transform` makes @ref result able to be a drop in replacement for
1748  /// `std::expected`. `map` is the more typical name of this monadic
1749  /// operation outside of C++.
1750  ///
1751  /// ## Example
1752  /// ```
1753  /// result<int, std::string> res1{42};
1754  /// result<int, std::string> res2{in_place_error, "oh no"};
1755  ///
1756  /// auto res1_mapped = std::move(res1).transform([](auto value) {
1757  /// return std::to_string(value);
1758  /// });
1759  /// auto res2_mapped = std::move(res2).transform([](auto value) {
1760  /// return std::to_string(value);
1761  /// });
1762  ///
1763  /// assert(res1_mapped.is_error());
1764  /// assert(res1_mapped.error() == "oh no");
1765  ///
1766  /// assert(res2_mapped.is_ok());
1767  /// assert(*res2_mapped == "42");
1768  /// ```
1769  template <typename F>
1770  constexpr auto transform(F&& f) && {
1771  if constexpr (std::is_void_v<T>) {
1772  using res_t = std::invoke_result_t<F, void_t>;
1773  if (res_().index() == 0) {
1774  if constexpr (std::is_void_v<res_t>) {
1775  std::invoke(std::forward<F>(f), void_v);
1776  return result<res_t, E>{std::in_place};
1777  } else {
1778  return result<res_t, E>{std::in_place,
1779  std::invoke(std::forward<F>(f), void_v)};
1780  }
1781  } else {
1782  if constexpr (std::is_void_v<E>) {
1783  return result<res_t, E>{in_place_error};
1784  } else {
1785  return result<res_t, E>{in_place_error,
1786  std::move(*this).res_()[index<1>]};
1787  }
1788  }
1789  } else {
1790  using res_t = std::invoke_result_t<F, rvalue_reference>;
1791  if (res_().index() == 0) {
1792  if constexpr (std::is_void_v<res_t>) {
1793  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>]);
1794  return result<res_t, E>{std::in_place};
1795  } else {
1796  return result<res_t, E>{
1797  std::in_place,
1798  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>])};
1799  }
1800  } else {
1801  if constexpr (std::is_void_v<E>) {
1802  return result<res_t, E>{in_place_error};
1803  } else {
1804  return result<res_t, E>{in_place_error,
1805  std::move(*this).res_()[index<1>]};
1806  }
1807  }
1808  }
1809  }
1810 
1811  /// @brief Perforams a transformation on the ok value of a @ref result
1812  ///
1813  /// @details
1814  /// If the @ref result contains an ok value, that value is passed to the
1815  /// transformation callable provided. The value returned from the callable
1816  /// is then returned from this function as the ok value of a new @ref
1817  /// result, where ok type of the new result is the exact type returned
1818  /// from the callable. If the @ref result contains an error value, the
1819  /// error is returned.
1820  ///
1821  /// Note that this function is identical to @ref map, but the name
1822  /// `transform` makes @ref result able to be a drop in replacement for
1823  /// `std::expected`. `map` is the more typical name of this monadic
1824  /// operation outside of C++.
1825  ///
1826  /// ## Example
1827  /// ```
1828  /// const result<int, std::string> res1{42};
1829  /// const result<int, std::string> res2{in_place_error, "oh no"};
1830  ///
1831  /// auto res1_mapped = std::move(res1).transform([](auto value) {
1832  /// return std::to_string(value);
1833  /// });
1834  /// auto res2_mapped = std::move(res2).transform([](auto value) {
1835  /// return std::to_string(value);
1836  /// });
1837  ///
1838  /// assert(res1_mapped.is_error());
1839  /// assert(res1_mapped.error() == "oh no");
1840  ///
1841  /// assert(res2_mapped.is_ok());
1842  /// assert(*res2_mapped == "42");
1843  /// ```
1844  template <typename F>
1845  constexpr auto transform(F&& f) const&& {
1846  if constexpr (std::is_void_v<T>) {
1847  using res_t = std::invoke_result_t<F, void_t>;
1848  if (res_().index() == 0) {
1849  if constexpr (std::is_void_v<res_t>) {
1850  std::invoke(std::forward<F>(f), void_v);
1851  return result<res_t, E>{std::in_place};
1852  } else {
1853  return result<res_t, E>{std::in_place,
1854  std::invoke(std::forward<F>(f), void_v)};
1855  }
1856  } else {
1857  if constexpr (std::is_void_v<E>) {
1858  return result<res_t, E>{in_place_error};
1859  } else {
1860  return result<res_t, E>{in_place_error,
1861  std::move(*this).res_()[index<1>]};
1862  }
1863  }
1864  } else {
1865  using res_t = std::invoke_result_t<F, const_rvalue_reference>;
1866  if (res_().index() == 0) {
1867  if constexpr (std::is_void_v<res_t>) {
1868  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>]);
1869  return result<res_t, E>{std::in_place};
1870  } else {
1871  return result<res_t, E>{
1872  std::in_place,
1873  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<0>])};
1874  }
1875  } else {
1876  if constexpr (std::is_void_v<E>) {
1877  return result<res_t, E>{in_place_error};
1878  } else {
1879  return result<res_t, E>{in_place_error,
1880  std::move(*this).res_()[index<1>]};
1881  }
1882  }
1883  }
1884  }
1885 
1886  /// @brief Perforams a transformation on the ok value of a @ref result
1887  ///
1888  /// @details
1889  /// If the @ref result contains an ok value, that value is passed to the
1890  /// transformation callable provided. The value returned from the callable
1891  /// is then returned from this function as the ok value of a new @ref
1892  /// result, where ok type of the new result is the exact type returned
1893  /// from the callable. If the @ref result contains an error value, a copy
1894  /// of the error is returned.
1895  ///
1896  /// Note that this function is idential to @ref transform, but the name
1897  /// `map` is the more typical name of this monadic operation outside of
1898  /// C++.
1899  ///
1900  /// ## Example
1901  /// ```
1902  /// result<int, std::string> res1{42};
1903  /// result<int, std::string> res2{in_place_error, "oh no"};
1904  ///
1905  /// auto res1_mapped = res1.map([](auto value) {
1906  /// return std::to_string(value);
1907  /// });
1908  /// auto res2_mapped = res2.map([](auto value) {
1909  /// return std::to_string(value);
1910  /// });
1911  ///
1912  /// assert(res1_mapped.is_error());
1913  /// assert(res1_mapped.error() == "oh no");
1914  ///
1915  /// assert(res2_mapped.is_ok());
1916  /// assert(*res2_mapped == "42");
1917  /// ```
1918  template <typename F>
1919  constexpr auto map(F&& f) & {
1920  return transform(std::forward<F>(f));
1921  }
1922 
1923  /// @brief Perforams a transformation on the ok value of a @ref result
1924  ///
1925  /// @details
1926  /// If the @ref result contains an ok value, that value is passed to the
1927  /// transformation callable provided. The value returned from the callable
1928  /// is then returned from this function as the ok value of a new @ref
1929  /// result, where ok type of the new result is the exact type returned
1930  /// from the callable. If the @ref result contains an error value, a copy
1931  /// of the error is returned.
1932  ///
1933  /// Note that this function is idential to @ref transform, but the name
1934  /// `map` is the more typical name of this monadic operation outside of
1935  /// C++.
1936  ///
1937  /// ## Example
1938  /// ```
1939  /// const result<int, std::string> res1{42};
1940  /// const result<int, std::string> res2{in_place_error, "oh no"};
1941  ///
1942  /// auto res1_mapped = res1.map([](auto value) {
1943  /// return std::to_string(value);
1944  /// });
1945  /// auto res2_mapped = res2.map([](auto value) {
1946  /// return std::to_string(value);
1947  /// });
1948  ///
1949  /// assert(res1_mapped.is_error());
1950  /// assert(res1_mapped.error() == "oh no");
1951  ///
1952  /// assert(res2_mapped.is_ok());
1953  /// assert(*res2_mapped == "42");
1954  /// ```
1955  template <typename F>
1956  constexpr auto map(F&& f) const& {
1957  return transform(std::forward<F>(f));
1958  }
1959 
1960  /// @brief Perforams a transformation on the ok value of a @ref result
1961  ///
1962  /// @details
1963  /// If the @ref result contains an ok value, that value is passed to the
1964  /// transformation callable provided. The value returned from the callable
1965  /// is then returned from this function as the ok value of a new @ref
1966  /// result, where ok type of the new result is the exact type returned
1967  /// from the callable. If the @ref result contains an error value, the
1968  /// error is returned.
1969  ///
1970  /// Note that this function is idential to @ref transform, but the name
1971  /// `map` is the more typical name of this monadic operation outside of
1972  /// C++.
1973  ///
1974  /// ## Example
1975  /// ```
1976  /// result<int, std::string> res1{42};
1977  /// result<int, std::string> res2{in_place_error, "oh no"};
1978  ///
1979  /// auto res1_mapped = std::move(res1).map([](auto value) {
1980  /// return std::to_string(value);
1981  /// });
1982  /// auto res2_mapped = std::move(res2).map([](auto value) {
1983  /// return std::to_string(value);
1984  /// });
1985  ///
1986  /// assert(res1_mapped.is_error());
1987  /// assert(res1_mapped.error() == "oh no");
1988  ///
1989  /// assert(res2_mapped.is_ok());
1990  /// assert(*res2_mapped == "42");
1991  /// ```
1992  template <typename F>
1993  constexpr auto map(F&& f) && {
1994  return std::move(*this).transform(std::forward<F>(f));
1995  }
1996 
1997  /// @brief Perforams a transformation on the ok value of a @ref result
1998  ///
1999  /// @details
2000  /// If the @ref result contains an ok value, that value is passed to the
2001  /// transformation callable provided. The value returned from the callable
2002  /// is then returned from this function as the ok value of a new @ref
2003  /// result, where ok type of the new result is the exact type returned
2004  /// from the callable. If the @ref result contains an error value, the
2005  /// error is returned.
2006  ///
2007  /// Note that this function is idential to @ref transform, but the name
2008  /// `map` is the more typical name of this monadic operation outside of
2009  /// C++.
2010  ///
2011  /// ## Example
2012  /// ```
2013  /// const result<int, std::string> res1{42};
2014  /// const result<int, std::string> res2{in_place_error, "oh no"};
2015  ///
2016  /// auto res1_mapped = std::move(res1).map([](auto value) {
2017  /// return std::to_string(value);
2018  /// });
2019  /// auto res2_mapped = std::move(res2).map([](auto value) {
2020  /// return std::to_string(value);
2021  /// });
2022  ///
2023  /// assert(res1_mapped.is_error());
2024  /// assert(res1_mapped.error() == "oh no");
2025  ///
2026  /// assert(res2_mapped.is_ok());
2027  /// assert(*res2_mapped == "42");
2028  /// ```
2029  template <typename F>
2030  constexpr auto map(F&& f) const&& {
2031  return std::move(*this).transform(std::forward<F>(f));
2032  }
2033 
2034  /// @brief Returns the result of invoking `f` if the @ref result is an error
2035  ///
2036  /// @details
2037  /// If the @ref result contains an ok value, a copy of the entire @ref
2038  /// result is returned. If the @ref result contains an error value, `f` is
2039  /// invoked with the error value as an argument, and the returned value
2040  /// from invoking `f` is returned from this function, converting to
2041  /// `result<T, E>` if necessary.
2042  ///
2043  /// ## Example
2044  /// ```
2045  /// result<int, std::string> res1{42};
2046  /// result<int, std::string> res2{in_place_error, "oh no"};
2047  ///
2048  /// auto res1_new = res1.or_else([]([[maybe_unused]] const auto& err) {
2049  /// return 0;
2050  /// });
2051  /// auto res2_new = res2.or_else([]([[maybe_unused]] const auto& err) {
2052  /// return 0;
2053  /// });
2054  ///
2055  /// assert(res1_new.is_ok());
2056  /// assert(*res1_new == 42);
2057  ///
2058  /// assert(res2_new.is_ok());
2059  /// assert(*res2_new == 0);
2060  /// ```
2061  template <typename F>
2062  constexpr result or_else(F&& f) const& {
2063  if (res_().index() == 0) {
2064  return *this;
2065  } else {
2066  if constexpr (std::is_void_v<E>) {
2067  return std::invoke(std::forward<F>(f), void_v);
2068  } else {
2069  return std::invoke(std::forward<F>(f), res_()[index<1>]);
2070  }
2071  }
2072  }
2073 
2074  /// @brief Returns the result of invoking `f` if the @ref result is an error
2075  ///
2076  /// @details
2077  /// If the @ref result contains an ok value, the entire @ref
2078  /// result is returned. If the @ref result contains an error value, `f` is
2079  /// invoked with the error value as an argument, and the returned value
2080  /// from invoking `f` is returned from this function, converting to
2081  /// `result<T, E>` if necessary.
2082  ///
2083  /// ## Example
2084  /// ```
2085  /// result<int, std::string> res1{42};
2086  /// result<int, std::string> res2{in_place_error, "oh no"};
2087  ///
2088  /// auto res1_new = std::move(res1).or_else([]([[maybe_unused]] auto err) {
2089  /// return 0;
2090  /// });
2091  /// auto res2_new = std::move(res2).or_else([]([[maybe_unused]] auto err) {
2092  /// return 0;
2093  /// });
2094  ///
2095  /// assert(res1_new.is_ok());
2096  /// assert(*res1_new == 42);
2097  ///
2098  /// assert(res2_new.is_ok());
2099  /// assert(*res2_new == 0);
2100  /// ```
2101  template <typename F>
2102  constexpr result or_else(F&& f) && {
2103  if (res_().index() == 0) {
2104  return std::move(*this);
2105  } else {
2106  if constexpr (std::is_void_v<E>) {
2107  return std::invoke(std::forward<F>(f), void_v);
2108  } else {
2109  return std::invoke(std::forward<F>(f), std::move(res_()[index<1>]));
2110  }
2111  }
2112  }
2113 
2114  /// @brief Converts `result<result<T, E1>, E2>` into `result<T, E3>`
2115  ///
2116  /// @details
2117  /// If the outer @ref result contains an error, a copy of that error is
2118  /// returned. If the outer @ref result contains an ok value, and the inner
2119  /// @ref result contains an error, a copy of that inner error is returned.
2120  /// If the outer @ref result contains an ok value and the inner @ref result
2121  /// contains an ok value, a copy of that inner ok value is returned.
2122  ///
2123  /// If the outer @ref result and the inner @ref result have different error
2124  /// types, the returned @ref result will be one of these two types based on
2125  /// the following priority rules:
2126  ///
2127  /// 1. If the outer error type is `void`, use the inner error type
2128  /// 2. Else, if the inner error type is `void`, use the outer error type
2129  /// 3. Else, if the outer error type is constructible from the inner error
2130  /// type, use the outer error type.
2131  /// 4. Else, if the inner error type is constructible from the outer error
2132  /// type, use the inner error type.
2133  ///
2134  /// Note that only one level of @ref result is removed. For example, a
2135  /// `result<result<result<T, E>, E>, E>` will flatten to a
2136  /// `result<result<T, E>, E>`.
2137  ///
2138  /// ## Example
2139  /// ```
2140  /// result<result<int, const char*>, std::string> res1{in_place, 42};
2141  /// result<result<int, const char*>, std::string> res2{
2142  /// in_place, in_place_error, "oh no"};
2143  /// result<result<int, const char*>, std::string> res3{
2144  /// in_place_error, "oh no"};
2145  ///
2146  /// result<int, std::string> res1_flat = res1.flatten();
2147  /// result<int, std::string> res2_flat = res2.flatten();
2148  /// result<int, std::string> res3_flat = res3.flatten();
2149  ///
2150  /// assert(res1_flat.is_ok());
2151  /// assert(*res1_flat == 42);
2152  ///
2153  /// assert(res2_flat.is_error());
2154  /// assert(res2_flat.error() == "oh no");
2155  ///
2156  /// assert(res3_flat.is_error());
2157  /// assert(res3_flat.error() == "oh no");
2158  /// ```
2159  [[nodiscard]] constexpr auto flatten() const&
2160 #ifndef DOXYGEN
2161  requires(detail::is_result_v<T>)
2162 #endif
2163  {
2164  if constexpr (std::is_void_v<typename T::error_type>) {
2165  using ret_t = result<typename T::value_type, E>;
2166  if (is_ok()) {
2167  return ret_t{res_()[index<0>]};
2168  } else {
2169  if constexpr (std::is_void_v<E>) {
2170  return ret_t{in_place_error};
2171  } else {
2172  return ret_t{in_place_error, error()};
2173  }
2174  }
2175  } else if constexpr (std::is_void_v<E>) {
2176  using ret_t = T;
2177  if (is_ok()) {
2178  return res_()[index<0>];
2179  } else {
2180  return ret_t{in_place_error, error()};
2181  }
2182  } else if constexpr (detail::traits<E>::template is_constructible<
2183  typename T::error_const_reference>) {
2184  using ret_t = result<typename T::value_type, E>;
2185  if (is_ok()) {
2186  return ret_t{res_()[index<0>]};
2187  } else {
2188  return ret_t{in_place_error, error()};
2189  }
2190  } else if constexpr (detail::traits<typename T::error_type>::
2191  template is_constructible<error_const_reference>) {
2192  using ret_t = T;
2193  if (is_ok()) {
2194  return res_()[index<0>];
2195  } else {
2196  return ret_t{in_place_error, error()};
2197  }
2198  }
2199  }
2200 
2201  /// @brief Converts `result<result<T, E1>, E2>` into `result<T, E3>`
2202  ///
2203  /// @details
2204  /// If the outer @ref result contains an error, that error is
2205  /// returned. If the outer @ref result contains an ok value, and the inner
2206  /// @ref result contains an error, that inner error is returned.
2207  /// If the outer @ref result contains an ok value and the inner @ref result
2208  /// contains an ok value, that inner ok value is returned.
2209  ///
2210  /// If the outer @ref result and the inner @ref result have different error
2211  /// types, the returned @ref result will be one of these two types based on
2212  /// the following priority rules:
2213  ///
2214  /// 1. If the outer error type is `void`, use the inner error type
2215  /// 2. Else, if the inner error type is `void`, use the outer error type
2216  /// 3. Else, if the outer error type is constructible from the inner error
2217  /// type, use the outer error type.
2218  /// 4. Else, if the inner error type is constructible from the outer error
2219  /// type, use the inner error type.
2220  ///
2221  /// Note that only one level of @ref result is removed. For example, a
2222  /// `result<result<result<T, E>, E>, E>` will flatten to a
2223  /// `result<result<T, E>, E>`.
2224  ///
2225  /// ## Example
2226  /// ```
2227  /// result<result<int, const char*>, std::string> res1{in_place, 42};
2228  /// result<result<int, const char*>, std::string> res2{
2229  /// in_place, in_place_error, "oh no"};
2230  /// result<result<int, const char*>, std::string> res3{
2231  /// in_place_error, "oh no"};
2232  ///
2233  /// result<int, std::string> res1_flat = std::move(res1).flatten();
2234  /// result<int, std::string> res2_flat = std::move(res2).flatten();
2235  /// result<int, std::string> res3_flat = std::move(res3).flatten();
2236  ///
2237  /// assert(res1_flat.is_ok());
2238  /// assert(*res1_flat == 42);
2239  ///
2240  /// assert(res2_flat.is_error());
2241  /// assert(res2_flat.error() == "oh no");
2242  ///
2243  /// assert(res3_flat.is_error());
2244  /// assert(res3_flat.error() == "oh no");
2245  /// ```
2246  [[nodiscard]] constexpr auto flatten() &&
2247 #ifndef DOXYGEN
2248  requires(detail::is_result_v<T>)
2249 #endif
2250  {
2251  if constexpr (std::is_void_v<typename T::error_type>) {
2252  using ret_t = result<typename T::value_type, E>;
2253  if (is_ok()) {
2254  return ret_t{std::move(res_()[index<0>])};
2255  } else {
2256  if constexpr (std::is_void_v<E>) {
2257  return ret_t{in_place_error};
2258  } else {
2259  return ret_t{in_place_error, std::move(error())};
2260  }
2261  }
2262  } else if constexpr (std::is_void_v<E>) {
2263  using ret_t = T;
2264  if (is_ok()) {
2265  return std::move(res_()[index<0>]);
2266  } else {
2267  return ret_t{in_place_error, std::move(error())};
2268  }
2269  } else if constexpr (detail::traits<E>::template is_constructible<
2270  typename T::error_rvalue_reference>) {
2271  using ret_t = result<typename T::value_type, E>;
2272  if (is_ok()) {
2273  return ret_t{std::move(res_()[index<0>])};
2274  } else {
2275  return ret_t{in_place_error, std::move(error())};
2276  }
2277  } else if constexpr (detail::traits<typename T::error_type>::
2278  template is_constructible<error_rvalue_reference>) {
2279  using ret_t = T;
2280  if (is_ok()) {
2281  return std::move(res_()[index<0>]);
2282  } else {
2283  return ret_t{in_place_error, std::move(error())};
2284  }
2285  }
2286  }
2287 
2288  /// @brief Converts nested @ref result types into a single @ref result
2289  ///
2290  /// @details
2291  /// Like @ref flatten, this function removes nested layers of @ref result,
2292  /// such as converting `result<result<T, E>, E>` into `result<T, E>`.
2293  /// However, unlike @ref flatten, this function removes all layers of
2294  /// nesting and works for unnested @ref result types. For example,
2295  /// `result<result<result<T, E>, E, E>` is converted directly to
2296  /// `result<T, E>`, and for `result<T, E>`, where `T` is not a @ref result
2297  /// type, no layers of @ref result are removed.
2298  ///
2299  /// ## Example
2300  /// ```
2301  /// using nested_result_t =
2302  /// result<result<result<int, std::string>, std::string, std::string>;
2303  ///
2304  /// nested_result_t res1{in_place, in_place, in_place, 42};
2305  /// nested_result_t res2{in_place_error, "oh no"};
2306  /// nested_result_t res3{in_place, in_place_error, "oh no"};
2307  /// nested_result_t res4{in_place, in_place, in_place_error, "oh no"};
2308  ///
2309  /// result<int, std::string> res1_flat = res1.flatten_all();
2310  /// result<int, std::string> res2_flat = res2.flatten_all();
2311  /// result<int, std::string> res3_flat = res3.flatten_all();
2312  /// result<int, std::string> res4_flat = res4.flatten_all();
2313  ///
2314  /// assert(res1_flat.is_ok());
2315  /// assert(*res1_flat == 42);
2316  ///
2317  /// assert(res2_flat.is_error());
2318  /// assert(res2_flat.error() == "oh no");
2319  ///
2320  /// assert(res3_flat.is_error());
2321  /// assert(res3_flat.error() == "oh no");
2322  ///
2323  /// assert(res3_flat.is_error());
2324  /// assert(res3_flat.error() == "oh no");
2325  /// ```
2326  [[nodiscard]] constexpr auto flatten_all() const& {
2327  if constexpr (detail::is_result_v<T>) {
2328  return flatten().flatten_all();
2329  } else {
2330  return *this;
2331  }
2332  }
2333 
2334  /// @brief Converts nested @ref result types into a single @ref result
2335  ///
2336  /// @details
2337  /// Like @ref flatten, this function removes nested layers of @ref result,
2338  /// such as converting `result<result<T, E>, E>` into `result<T, E>`.
2339  /// However, unlike @ref flatten, this function removes all layers of
2340  /// nesting and works for unnested @ref result types. For example,
2341  /// `result<result<result<T, E>, E, E>` is converted directly to
2342  /// `result<T, E>`, and for `result<T, E>`, where `T` is not a @ref result
2343  /// type, no layers of @ref result are removed.
2344  ///
2345  /// ## Example
2346  /// ```
2347  /// using nested_result_t =
2348  /// result<result<result<int, std::string>, std::string, std::string>;
2349  ///
2350  /// nested_result_t res1{in_place, in_place, in_place, 42};
2351  /// nested_result_t res2{in_place_error, "oh no"};
2352  /// nested_result_t res3{in_place, in_place_error, "oh no"};
2353  /// nested_result_t res4{in_place, in_place, in_place_error, "oh no"};
2354  ///
2355  /// result<int, std::string> res1_flat = std::move(res1).flatten_all();
2356  /// result<int, std::string> res2_flat = std::move(res2).flatten_all();
2357  /// result<int, std::string> res3_flat = std::move(res3).flatten_all();
2358  /// result<int, std::string> res4_flat = std::move(res4).flatten_all();
2359  ///
2360  /// assert(res1_flat.is_ok());
2361  /// assert(*res1_flat == 42);
2362  ///
2363  /// assert(res2_flat.is_error());
2364  /// assert(res2_flat.error() == "oh no");
2365  ///
2366  /// assert(res3_flat.is_error());
2367  /// assert(res3_flat.error() == "oh no");
2368  ///
2369  /// assert(res3_flat.is_error());
2370  /// assert(res3_flat.error() == "oh no");
2371  /// ```
2372  [[nodiscard]] constexpr auto flatten_all() && {
2373  if constexpr (detail::is_result_v<T>) {
2374  return std::move(*this).flatten().flatten_all();
2375  } else {
2376  return std::move(*this);
2377  }
2378  }
2379 
2380  /// @brief Converts `result<option<T>, E>` into `option<result<T, E>>`
2381  ///
2382  /// @details
2383  /// If the @ref result contains an error, the return value will be a @ref
2384  /// option that contains a @ref result that contains an error. If the @ref
2385  /// result contains an @ref option that contains a value, the return value
2386  /// will be a @ref option that contains @ref result that contains an ok
2387  /// value. If the @ref result contains a @ref option that is `none`, the
2388  /// return value will be an @ref option that is `none`.
2389  ///
2390  /// This function only participates in overload resolution of `T` is an
2391  /// @ref option.
2392  ///
2393  /// ## Example
2394  /// ```
2395  /// result<option<int>, std::string> val1{42};
2396  /// result<option<int>, std::string> val2{none};
2397  /// result<option<int>, std::string> val3{in_place_error, "oh no"};
2398  ///
2399  /// auto val1_trans = val1.transpose();
2400  /// auto val2_trans = val2.transpose();
2401  /// auto val3_trans = val3.transpose();
2402  ///
2403  /// assert(val1_trans.is_some());
2404  /// assert(val1_trans->is_ok());
2405  /// assert(**val1_trans == 42);
2406  ///
2407  /// assert(val2_trans.is_none());
2408  ///
2409  /// assert(val3_trans.is_some());
2410  /// assert(val3_trans->is_error());
2411  /// assert(val3_trans->error() == "oh no");
2412  /// ```
2413  [[nodiscard]] constexpr auto transpose() const&
2414 #ifndef DOXYGEN
2415  requires(detail::is_option_v<T>)
2416 #endif
2417  {
2418  using ret_t = option<result<typename T::value_type, E>>;
2419  if (is_ok()) {
2420  if (res_()[index<0>].is_some()) {
2421  return ret_t{in_place, in_place, *res_()[index<0>]};
2422  } else {
2423  return ret_t{none};
2424  }
2425  } else {
2426  return ret_t{in_place, in_place_error, error()};
2427  }
2428  }
2429 
2430  /// @brief Converts `result<option<T>, E>` into `option<result<T, E>>`
2431  ///
2432  /// @details
2433  /// If the @ref result contains an error, the return value will be a @ref
2434  /// option that contains a @ref result that contains an error. If the @ref
2435  /// result contains an @ref option that contains a value, the return value
2436  /// will be a @ref option that contains @ref result that contains an ok
2437  /// value. If the @ref result contains a @ref option that is `none`, the
2438  /// return value will be an @ref option that is `none`.
2439  ///
2440  /// This function only participates in overload resolution of `T` is an
2441  /// @ref option.
2442  ///
2443  /// ## Example
2444  /// ```
2445  /// result<option<int>, std::string> val1{42};
2446  /// result<option<int>, std::string> val2{none};
2447  /// result<option<int>, std::string> val3{in_place_error, "oh no"};
2448  ///
2449  /// auto val1_trans = std::move(val1).transpose();
2450  /// auto val2_trans = std::move(val2).transpose();
2451  /// auto val3_trans = std::move(val3).transpose();
2452  ///
2453  /// assert(val1_trans.is_some());
2454  /// assert(val1_trans->is_ok());
2455  /// assert(**val1_trans == 42);
2456  ///
2457  /// assert(val2_trans.is_none());
2458  ///
2459  /// assert(val3_trans.is_some());
2460  /// assert(val3_trans->is_error());
2461  /// assert(val3_trans->error() == "oh no");
2462  /// ```
2463  [[nodiscard]] constexpr auto transpose() &&
2464 #ifndef DOXYGEN
2465  requires(detail::is_option_v<T>)
2466 #endif
2467  {
2468  using ret_t = option<result<typename T::value_type, E>>;
2469  if (is_ok()) {
2470  if (res_()[index<0>].is_some()) {
2471  return ret_t{in_place, in_place, std::move(*res_()[index<0>])};
2472  } else {
2473  return ret_t{none};
2474  }
2475  } else {
2476  return ret_t{in_place, in_place_error, std::move(error())};
2477  }
2478  }
2479 
2480  /// @brief Swaps the ok and error types of a @ref result
2481  ///
2482  /// @details
2483  /// If the @ref result contains an ok value, a copy of the ok value will be
2484  /// returned as an error. If the @ref result contains an error value, the
2485  /// error value will be returned as an ok value.
2486  ///
2487  /// ## Example
2488  /// ```
2489  /// result<int, std::string> res1{42};
2490  /// result<int, std::string> res2{in_place_error, "oh no"};
2491  ///
2492  /// result<std::string, int> res1_inv = res1.invert();
2493  /// result<std::string, int> res2_inv = res2.invert();
2494  ///
2495  /// assert(res1_inv.is_error());
2496  /// assert(res1_inv.error() == 42);
2497  ///
2498  /// assert(res2_inv.is_ok());
2499  /// assert(*res2_inv == "oh no");
2500  /// ```
2501  [[nodiscard]] constexpr result<E, T> invert() const& {
2502  if (is_ok()) {
2503  return result<E, T>{in_place_error, res_()[0]};
2504  } else {
2505  return result<E, T>{in_place, error()};
2506  }
2507  }
2508 
2509  /// @brief Swaps the ok and error types of a @ref result
2510  ///
2511  /// @details
2512  /// If the @ref result contains an ok value, a copy of the ok value will be
2513  /// returned as an error. If the @ref result contains an error value, the
2514  /// error value will be returned as an ok value.
2515  ///
2516  /// ## Example
2517  /// ```
2518  /// result<int, std::string> res1{42};
2519  /// result<int, std::string> res2{in_place_error, "oh no"};
2520  ///
2521  /// result<std::string, int> res1_inv = std::move(res1).invert();
2522  /// result<std::string, int> res2_inv = std::move(res2).invert();
2523  ///
2524  /// assert(res1_inv.is_error());
2525  /// assert(res1_inv.error() == 42);
2526  ///
2527  /// assert(res2_inv.is_ok());
2528  /// assert(*res2_inv == "oh no");
2529  /// ```
2530  [[nodiscard]] constexpr result<E, T> invert() && {
2531  if (is_ok()) {
2532  return result<E, T>{in_place_error, std::move(res_()[0])};
2533  } else {
2534  return result<E, T>{in_place, std::move(error())};
2535  }
2536  }
2537 
2538  /// @brief Perforams a transformation on the error value of a @ref result
2539  ///
2540  /// @details
2541  /// If the @ref result contains an error value, that value is passed to the
2542  /// transformation callable provided. The value returned from the callable
2543  /// is then returned from this function as the error value of a new @ref
2544  /// result, where the error type of the new result is the exact type
2545  /// returned from the callable. If the @ref result contains an ok value, a
2546  /// copy of the ok value is returned.
2547  ///
2548  /// Note that this function is identical to @ref map_error, but the name
2549  /// `transform_error` makes @ref result able to be a drop in replacement
2550  /// for `std::expected`. `map_error` would be the more typical name of
2551  /// this monadic operation outside of C++.
2552  ///
2553  /// ## Example
2554  /// ```
2555  /// result<void, int> res1{};
2556  /// result<void, int> res2{in_place_error, 42};
2557  ///
2558  /// auto res1_mapped = res1.transform_error([](auto value) {
2559  /// return std::to_string(value);
2560  /// });
2561  /// auto res2_mapped = res2.transform_error([](auto value) {
2562  /// return std::to_string(value);
2563  /// });
2564  ///
2565  /// assert(res1_mapped.is_ok());
2566  ///
2567  /// assert(res2_mapped.is_error());
2568  /// assert(*res2_mapped == "42");
2569  /// ```
2570  template <typename F>
2571  constexpr auto transform_error(F&& f) & {
2572  if constexpr (std::is_void_v<E>) {
2573  using res_t = std::invoke_result_t<F, void_t>;
2574  if (res_().index() != 0) {
2575  if constexpr (std::is_void_v<res_t>) {
2576  std::invoke(std::forward<F>(f), void_v);
2577  return result<T, res_t>{in_place_error};
2578  } else {
2579  return result<T, res_t>{in_place_error,
2580  std::invoke(std::forward<F>(f), void_v)};
2581  }
2582  } else {
2583  if constexpr (std::is_void_v<T>) {
2584  return result<T, res_t>{std::in_place};
2585  } else {
2586  return result<T, res_t>{std::in_place, res_()[index<0>]};
2587  }
2588  }
2589  } else {
2590  using res_t = std::invoke_result_t<F, error_reference>;
2591  if (res_().index() != 0) {
2592  if constexpr (std::is_void_v<res_t>) {
2593  std::invoke(std::forward<F>(f), res_()[index<1>]);
2594  return result<T, res_t>{in_place_error};
2595  } else {
2596  return result<T, res_t>{
2597  in_place_error, std::invoke(std::forward<F>(f), res_()[index<1>])};
2598  }
2599  } else {
2600  if constexpr (std::is_void_v<T>) {
2601  return result<T, res_t>{std::in_place};
2602  } else {
2603  return result<T, res_t>{std::in_place, res_()[index<0>]};
2604  }
2605  }
2606  }
2607  }
2608 
2609  /// @brief Perforams a transformation on the error value of a @ref result
2610  ///
2611  /// @details
2612  /// If the @ref result contains an error value, that value is passed to the
2613  /// transformation callable provided. The value returned from the callable
2614  /// is then returned from this function as the error value of a new @ref
2615  /// result, where the error type of the new result is the exact type
2616  /// returned from the callable. If the @ref result contains an ok value, a
2617  /// copy of the ok value is returned.
2618  ///
2619  /// Note that this function is identical to @ref map_error, but the name
2620  /// `transform_error` makes @ref result able to be a drop in replacement
2621  /// for `std::expected`. `map_error` would be the more typical name of
2622  /// this monadic operation outside of C++.
2623  ///
2624  /// ## Example
2625  /// ```
2626  /// const result<void, int> res1{};
2627  /// const result<void, int> res2{in_place_error, 42};
2628  ///
2629  /// auto res1_mapped = res1.transform_error([](auto value) {
2630  /// return std::to_string(value);
2631  /// });
2632  /// auto res2_mapped = res2.transform_error([](auto value) {
2633  /// return std::to_string(value);
2634  /// });
2635  ///
2636  /// assert(res1_mapped.is_ok());
2637  ///
2638  /// assert(res2_mapped.is_error());
2639  /// assert(*res2_mapped == "42");
2640  /// ```
2641  template <typename F>
2642  constexpr auto transform_error(F&& f) const& {
2643  if constexpr (std::is_void_v<E>) {
2644  using res_t = std::invoke_result_t<F, void_t>;
2645  if (res_().index() != 0) {
2646  if constexpr (std::is_void_v<res_t>) {
2647  std::invoke(std::forward<F>(f), void_v);
2648  return result<T, res_t>{in_place_error};
2649  } else {
2650  return result<T, res_t>{in_place_error,
2651  std::invoke(std::forward<F>(f), void_v)};
2652  }
2653  } else {
2654  if constexpr (std::is_void_v<T>) {
2655  return result<T, res_t>{std::in_place};
2656  } else {
2657  return result<T, res_t>{std::in_place, res_()[index<0>]};
2658  }
2659  }
2660  } else {
2661  using res_t = std::invoke_result_t<F, error_const_reference>;
2662  if (res_().index() != 0) {
2663  if constexpr (std::is_void_v<res_t>) {
2664  std::invoke(std::forward<F>(f), res_()[index<1>]);
2665  return result<T, res_t>{in_place_error};
2666  } else {
2667  return result<T, res_t>{
2668  in_place_error, std::invoke(std::forward<F>(f), res_()[index<1>])};
2669  }
2670  } else {
2671  if constexpr (std::is_void_v<T>) {
2672  return result<T, res_t>{std::in_place};
2673  } else {
2674  return result<T, res_t>{std::in_place, res_()[index<0>]};
2675  }
2676  }
2677  }
2678  }
2679 
2680  /// @brief Perforams a transformation on the error value of a @ref result
2681  ///
2682  /// @details
2683  /// If the @ref result contains an error value, that value is passed to the
2684  /// transformation callable provided. The value returned from the callable
2685  /// is then returned from this function as the error value of a new @ref
2686  /// result, where the error type of the new result is the exact type
2687  /// returned from the callable. If the @ref result contains an ok value,
2688  /// the ok value is returned.
2689  ///
2690  /// Note that this function is identical to @ref map_error, but the name
2691  /// `transform_error` makes @ref result able to be a drop in replacement
2692  /// for `std::expected`. `map_error` would be the more typical name of
2693  /// this monadic operation outside of C++.
2694  ///
2695  /// ## Example
2696  /// ```
2697  /// result<void, int> res1{};
2698  /// result<void, int> res2{in_place_error, 42};
2699  ///
2700  /// auto res1_mapped = std::move(res1).transform_error([](auto value) {
2701  /// return std::to_string(value);
2702  /// });
2703  /// auto res2_mapped = std::move(res2).transform_error([](auto value) {
2704  /// return std::to_string(value);
2705  /// });
2706  ///
2707  /// assert(res1_mapped.is_ok());
2708  ///
2709  /// assert(res2_mapped.is_error());
2710  /// assert(*res2_mapped == "42");
2711  /// ```
2712  template <typename F>
2713  constexpr auto transform_error(F&& f) && {
2714  if constexpr (std::is_void_v<E>) {
2715  using res_t = std::invoke_result_t<F, void_t>;
2716  if (res_().index() != 0) {
2717  if constexpr (std::is_void_v<res_t>) {
2718  std::invoke(std::forward<F>(f), void_v);
2719  return result<T, res_t>{in_place_error};
2720  } else {
2721  return result<T, res_t>{in_place_error,
2722  std::invoke(std::forward<F>(f), void_v)};
2723  }
2724  } else {
2725  if constexpr (std::is_void_v<T>) {
2726  return result<T, res_t>{std::in_place};
2727  } else {
2728  return result<T, res_t>{std::in_place,
2729  std::move(*this).res_()[index<0>]};
2730  }
2731  }
2732  } else {
2733  using res_t = std::invoke_result_t<F, error_rvalue_reference>;
2734  if (res_().index() != 0) {
2735  if constexpr (std::is_void_v<res_t>) {
2736  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<1>]);
2737  return result<T, res_t>{in_place_error};
2738  } else {
2739  return result<T, res_t>{
2740  in_place_error,
2741  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<1>])};
2742  }
2743  } else {
2744  if constexpr (std::is_void_v<T>) {
2745  return result<T, res_t>{std::in_place};
2746  } else {
2747  return result<T, res_t>{std::in_place,
2748  std::move(*this).res_()[index<0>]};
2749  }
2750  }
2751  }
2752  }
2753 
2754  /// @brief Perforams a transformation on the error value of a @ref result
2755  ///
2756  /// @details
2757  /// If the @ref result contains an error value, that value is passed to the
2758  /// transformation callable provided. The value returned from the callable
2759  /// is then returned from this function as the error value of a new @ref
2760  /// result, where the error type of the new result is the exact type
2761  /// returned from the callable. If the @ref result contains an ok value,
2762  /// the ok value is returned.
2763  ///
2764  /// Note that this function is identical to @ref map_error, but the name
2765  /// `transform_error` makes @ref result able to be a drop in replacement
2766  /// for `std::expected`. `map_error` would be the more typical name of
2767  /// this monadic operation outside of C++.
2768  ///
2769  /// ## Example
2770  /// ```
2771  /// const result<void, int> res1{};
2772  /// const result<void, int> res2{in_place_error, 42};
2773  ///
2774  /// auto res1_mapped = std::move(res1).transform_error([](auto value) {
2775  /// return std::to_string(value);
2776  /// });
2777  /// auto res2_mapped = std::move(res2).transform_error([](auto value) {
2778  /// return std::to_string(value);
2779  /// });
2780  ///
2781  /// assert(res1_mapped.is_ok());
2782  ///
2783  /// assert(res2_mapped.is_error());
2784  /// assert(*res2_mapped == "42");
2785  /// ```
2786  template <typename F>
2787  constexpr auto transform_error(F&& f) const&& {
2788  if constexpr (std::is_void_v<E>) {
2789  using res_t = std::invoke_result_t<F, void_t>;
2790  if (res_().index() != 0) {
2791  if constexpr (std::is_void_v<res_t>) {
2792  std::invoke(std::forward<F>(f));
2793  return result<T, res_t>{in_place_error};
2794  } else {
2795  return result<T, res_t>{in_place_error,
2796  std::invoke(std::forward<F>(f), void_v)};
2797  }
2798  } else {
2799  if constexpr (std::is_void_v<T>) {
2800  return result<T, res_t>{std::in_place};
2801  } else {
2802  return result<T, res_t>{std::in_place,
2803  std::move(*this).res_()[index<0>]};
2804  }
2805  }
2806  } else {
2807  using res_t = std::invoke_result_t<F, error_const_rvalue_reference>;
2808  if (res_().index() != 0) {
2809  if constexpr (std::is_void_v<res_t>) {
2810  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<1>]);
2811  return result<T, res_t>{in_place_error};
2812  } else {
2813  return result<T, res_t>{
2814  in_place_error,
2815  std::invoke(std::forward<F>(f), std::move(*this).res_()[index<1>])};
2816  }
2817  } else {
2818  if constexpr (std::is_void_v<T>) {
2819  return result<T, res_t>{std::in_place};
2820  } else {
2821  return result<T, res_t>{std::in_place,
2822  std::move(*this).res_()[index<0>]};
2823  }
2824  }
2825  }
2826  }
2827 
2828  /// @brief Perforams a transformation on the error value of a @ref result
2829  ///
2830  /// @details
2831  /// If the @ref result contains an error value, that value is passed to the
2832  /// transformation callable provided. The value returned from the callable
2833  /// is then returned from this function as the error value of a new @ref
2834  /// result, where the error type of the new result is the exact type
2835  /// returned from the callable. If the @ref result contains an ok value, a
2836  /// copy of the ok value is returned.
2837  ///
2838  /// Note that this function is identical to @ref transform_error, but the
2839  /// name `map_error` is more typical for this sort of monadic operation
2840  /// outside of C++.
2841  ///
2842  /// ## Example
2843  /// ```
2844  /// result<void, int> res1{};
2845  /// result<void, int> res2{in_place_error, 42};
2846  ///
2847  /// auto res1_mapped = res1.map_error([](auto value) {
2848  /// return std::to_string(value);
2849  /// });
2850  /// auto res2_mapped = res2.map_error([](auto value) {
2851  /// return std::to_string(value);
2852  /// });
2853  ///
2854  /// assert(res1_mapped.is_ok());
2855  ///
2856  /// assert(res2_mapped.is_error());
2857  /// assert(*res2_mapped == "42");
2858  /// ```
2859  template <typename F>
2860  constexpr auto map_error(F&& f) & {
2861  return transform_error(std::forward<F>(f));
2862  }
2863 
2864  /// @brief Perforams a transformation on the error value of a @ref result
2865  ///
2866  /// @details
2867  /// If the @ref result contains an error value, that value is passed to the
2868  /// transformation callable provided. The value returned from the callable
2869  /// is then returned from this function as the error value of a new @ref
2870  /// result, where the error type of the new result is the exact type
2871  /// returned from the callable. If the @ref result contains an ok value, a
2872  /// copy of the ok value is returned.
2873  ///
2874  /// Note that this function is identical to @ref transform_error, but the
2875  /// name `map_error` is more typical for this sort of monadic operation
2876  /// outside of C++.
2877  ///
2878  /// ## Example
2879  /// ```
2880  /// const result<void, int> res1{};
2881  /// const result<void, int> res2{in_place_error, 42};
2882  ///
2883  /// auto res1_mapped = res1.map_error([](auto value) {
2884  /// return std::to_string(value);
2885  /// });
2886  /// auto res2_mapped = res2.map_error([](auto value) {
2887  /// return std::to_string(value);
2888  /// });
2889  ///
2890  /// assert(res1_mapped.is_ok());
2891  ///
2892  /// assert(res2_mapped.is_error());
2893  /// assert(*res2_mapped == "42");
2894  /// ```
2895  template <typename F>
2896  constexpr auto map_error(F&& f) const& {
2897  return transform_error(std::forward<F>(f));
2898  }
2899 
2900  /// @brief Perforams a transformation on the error value of a @ref result
2901  ///
2902  /// @details
2903  /// If the @ref result contains an error value, that value is passed to the
2904  /// transformation callable provided. The value returned from the callable
2905  /// is then returned from this function as the error value of a new @ref
2906  /// result, where the error type of the new result is the exact type
2907  /// returned from the callable. If the @ref result contains an ok value,
2908  /// the ok value is returned.
2909  ///
2910  /// Note that this function is identical to @ref transform_error, but the
2911  /// name `map_error` is more typical for this sort of monadic operation
2912  /// outside of C++.
2913  ///
2914  /// ## Example
2915  /// ```
2916  /// result<void, int> res1{};
2917  /// result<void, int> res2{in_place_error, 42};
2918  ///
2919  /// auto res1_mapped = std::move(res1).map_error([](auto value) {
2920  /// return std::to_string(value);
2921  /// });
2922  /// auto res2_mapped = std::move(res2).map_error([](auto value) {
2923  /// return std::to_string(value);
2924  /// });
2925  ///
2926  /// assert(res1_mapped.is_ok());
2927  ///
2928  /// assert(res2_mapped.is_error());
2929  /// assert(*res2_mapped == "42");
2930  /// ```
2931  template <typename F>
2932  constexpr auto map_error(F&& f) && {
2933  return std::move(*this).transform_error(std::forward<F>(f));
2934  }
2935 
2936  /// @brief Perforams a transformation on the error value of a @ref result
2937  ///
2938  /// @details
2939  /// If the @ref result contains an error value, that value is passed to the
2940  /// transformation callable provided. The value returned from the callable
2941  /// is then returned from this function as the error value of a new @ref
2942  /// result, where the error type of the new result is the exact type
2943  /// returned from the callable. If the @ref result contains an ok value,
2944  /// the ok value is returned.
2945  ///
2946  /// Note that this function is identical to @ref transform_error, but the
2947  /// name `map_error` is more typical for this sort of monadic operation
2948  /// outside of C++.
2949  ///
2950  /// ## Example
2951  /// ```
2952  /// result<void, int> res1{};
2953  /// result<void, int> res2{in_place_error, 42};
2954  ///
2955  /// auto res1_mapped = std::move(res1).map_error([](auto value) {
2956  /// return std::to_string(value);
2957  /// });
2958  /// auto res2_mapped = std::move(res2).map_error([](auto value) {
2959  /// return std::to_string(value);
2960  /// });
2961  ///
2962  /// assert(res1_mapped.is_ok());
2963  ///
2964  /// assert(res2_mapped.is_error());
2965  /// assert(*res2_mapped == "42");
2966  /// ```
2967  template <typename F>
2968  constexpr auto map_error(F&& f) const&& {
2969  return std::move(*this).transform_error(std::forward<F>(f));
2970  }
2971 
2972  /// @brief Converts a @ref result reference into a @ref result of references
2973  ///
2974  /// @details
2975  /// ## Example
2976  /// ```
2977  /// result<int, std::string> res1{42};
2978  /// result<int, std::string> res2{in_place_error, "oh no"};
2979  ///
2980  /// result<int&, std::string&> res1_ref = res1.ref();
2981  /// result<int&, std::string&> ref2_ref = res2.ref();
2982  ///
2983  /// assert(res1_ref.is_ok());
2984  /// assert(&*res1_ref == &*res1);
2985  ///
2986  /// assert(res2_ref.is_error());
2987  /// assert(&res2_ref.error() == &res2.error());
2988  /// ```
2989  [[nodiscard]] constexpr result<reference, error_reference> ref() noexcept {
2990  if (res_().index() == 0) {
2991  if constexpr (std::is_void_v<T>) {
2992  return result<reference, error_reference>{std::in_place};
2993  } else {
2994  return result<reference, error_reference>{std::in_place, **this};
2995  }
2996  } else {
2997  if constexpr (std::is_void_v<E>) {
2998  return result<reference, error_reference>{in_place_error};
2999  } else {
3000  return result<reference, error_reference>{in_place_error, error()};
3001  }
3002  }
3003  }
3004 
3005  /// @brief Converts a @ref result reference into a @ref result of references
3006  ///
3007  /// @details
3008  /// ## Example
3009  /// ```
3010  /// const result<int, std::string> res1{42};
3011  /// const result<int, std::string> res2{in_place_error, "oh no"};
3012  ///
3013  /// result<const int&, const std::string&> res1_ref = res1.ref();
3014  /// result<const int&, const std::string&> ref2_ref = res2.ref();
3015  ///
3016  /// assert(res1_ref.is_ok());
3017  /// assert(&*res1_ref == &*res1);
3018  ///
3019  /// assert(res2_ref.is_error());
3020  /// assert(&res2_ref.error() == &res2.error());
3021  /// ```
3022  [[nodiscard]] constexpr result<const_reference, error_const_reference> ref()
3023  const noexcept {
3024  if (res_().index() == 0) {
3025  if constexpr (std::is_void_v<T>) {
3026  return result<const_reference, error_const_reference>{std::in_place};
3027  } else {
3028  return result<const_reference, error_const_reference>{std::in_place,
3029  **this};
3030  }
3031  } else {
3032  if constexpr (std::is_void_v<E>) {
3033  return result<const_reference, error_const_reference>{in_place_error};
3034  } else {
3035  return result<const_reference, error_const_reference>{in_place_error,
3036  error()};
3037  }
3038  }
3039  }
3040 
3041  /// @brief Converts a @ref result reference into a @ref result of references
3042  ///
3043  /// @details
3044  /// ## Example
3045  /// ```
3046  /// result<int, std::string> res1{42};
3047  /// result<int, std::string> res2{in_place_error, "oh no"};
3048  ///
3049  /// result<const int&, const std::string&> res1_ref = res1.cref();
3050  /// result<const int&, const std::string&> ref2_ref = res2.cref();
3051  ///
3052  /// assert(res1_ref.is_ok());
3053  /// assert(&*res1_ref == &*res1);
3054  ///
3055  /// assert(res2_ref.is_error());
3056  /// assert(&res2_ref.error() == &res2.error());
3057  /// ```
3058  [[nodiscard]] constexpr result<const_reference, error_const_reference> cref()
3059  const noexcept {
3060  return ref();
3061  }
3062 
3063  /// @brief Discards error values and converts into an @ref option
3064  ///
3065  /// @details
3066  /// If the @ref result contains an ok value, a copy of that value is
3067  /// returned wrapped in an @ref option. If the @ref result contains an
3068  /// error, `none` is returned.
3069  ///
3070  /// ## Example
3071  /// ```
3072  /// result<int, std::string> res1{42};
3073  /// result<int, std::string> res2{in_place_error, "oh no"};
3074  ///
3075  /// option<int> opt1 = res1.or_none();
3076  /// option<int> opt2 = res2.or_none();
3077  ///
3078  /// assert(opt1.is_some());
3079  /// assert(*opt1 == 42);
3080  ///
3081  /// assert(opt2.is_none());
3082  /// ```
3083  [[nodiscard]] constexpr option<T> or_none() const& noexcept {
3084  if (res_().index() == 0) {
3085  if constexpr (std::is_void_v<T>) {
3086  return option<T>{std::in_place};
3087  } else {
3088  return option<T>{std::in_place, res_()[index<0>]};
3089  }
3090  } else {
3091  return option<T>{};
3092  }
3093  }
3094 
3095  /// @brief Discards error values and converts into an @ref option
3096  ///
3097  /// @details
3098  /// If the @ref result contains an ok value, that value is
3099  /// returned wrapped in an @ref option. If the @ref result contains an
3100  /// error, `none` is returned.
3101  ///
3102  /// ## Example
3103  /// ```
3104  /// result<int, std::string> res1{42};
3105  /// result<int, std::string> res2{in_place_error, "oh no"};
3106  ///
3107  /// option<int> opt1 = std::move(res1).or_none();
3108  /// option<int> opt2 = std::move(res2).or_none();
3109  ///
3110  /// assert(opt1.is_some());
3111  /// assert(*opt1 == 42);
3112  ///
3113  /// assert(opt2.is_none());
3114  /// ```
3115  [[nodiscard]] constexpr option<T> or_none() && {
3116  if (res_().index() == 0) {
3117  if constexpr (std::is_void_v<T>) {
3118  return option<T>{std::in_place};
3119  } else {
3120  return option<T>{std::in_place, std::move(*this).res_()[index<0>]};
3121  }
3122  } else {
3123  return option<T>{};
3124  }
3125  }
3126 
3127  /// @brief Discards error values and converts into an @ref option
3128  ///
3129  /// @details
3130  /// If the @ref result contains an ok value, a copy of that value is
3131  /// returned wrapped in an @ref option. If the @ref result contains an
3132  /// error, `none` is returned.
3133  ///
3134  /// ## Example
3135  /// ```
3136  /// result<int, std::string> res1{42};
3137  /// result<int, std::string> res2{in_place_error, "oh no"};
3138  ///
3139  /// option<int> opt1 = res1.ok_or_none();
3140  /// option<int> opt2 = res2.ok_or_none();
3141  ///
3142  /// assert(opt1.is_some());
3143  /// assert(*opt1 == 42);
3144  ///
3145  /// assert(opt2.is_none());
3146  /// ```
3147  [[nodiscard]] constexpr option<T> ok_or_none() const& noexcept { return or_none(); }
3148 
3149  /// @brief Discards error values and converts into an @ref option
3150  ///
3151  /// @details
3152  /// If the @ref result contains an ok value, that value is
3153  /// returned wrapped in an @ref option. If the @ref result contains an
3154  /// error, `none` is returned.
3155  ///
3156  /// ## Example
3157  /// ```
3158  /// result<int, std::string> res1{42};
3159  /// result<int, std::string> res2{in_place_error, "oh no"};
3160  ///
3161  /// option<int> opt1 = std::move(res1).ok_or_none();
3162  /// option<int> opt2 = std::move(res2).ok_or_none();
3163  ///
3164  /// assert(opt1.is_some());
3165  /// assert(*opt1 == 42);
3166  ///
3167  /// assert(opt2.is_none());
3168  /// ```
3169  [[nodiscard]] constexpr option<T> ok_or_none() && { return std::move(*this).or_none(); }
3170 
3171  /// @brief Discards ok value and converts into an @ref option
3172  ///
3173  /// @details
3174  /// If the @ref result contains an error value, a copy of that value is
3175  /// returned wrapped in an @ref option. If the @ref result contains an ok
3176  /// value, `none` is returned.
3177  ///
3178  /// ## Example
3179  /// ```
3180  /// result<int, std::string> res1{42};
3181  /// result<int, std::string> res2{in_place_error, "oh no"};
3182  ///
3183  /// option<std::string> opt1 = res1.error_or_none();
3184  /// option<std::string> opt2 = res2.error_or_none();
3185  ///
3186  /// assert(opt1.is_none());
3187  ///
3188  /// assert(opt2.is_some());
3189  /// assert(*opt2 == "oh no");
3190  /// ```
3191  [[nodiscard]] constexpr option<E> error_or_none() const& noexcept {
3192  if (res_().index() != 0) {
3193  if constexpr (std::is_void_v<E>) {
3194  return option<E>{std::in_place};
3195  } else {
3196  return option<E>{std::in_place, res_()[index<1>]};
3197  }
3198  } else {
3199  return option<E>{};
3200  }
3201  }
3202 
3203  /// @brief Discards ok value and converts into an @ref option
3204  ///
3205  /// @details
3206  /// If the @ref result contains an error value, that value is
3207  /// returned wrapped in an @ref option. If the @ref result contains an ok
3208  /// value, `none` is returned.
3209  ///
3210  /// ## Example
3211  /// ```
3212  /// result<int, std::string> res1{42};
3213  /// result<int, std::string> res2{in_place_error, "oh no"};
3214  ///
3215  /// option<std::string> opt1 = res1.error_or_none();
3216  /// option<std::string> opt2 = res2.error_or_none();
3217  ///
3218  /// assert(opt1.is_none());
3219  ///
3220  /// assert(opt2.is_some());
3221  /// assert(*opt2 == "oh no");
3222  /// ```
3223  [[nodiscard]] constexpr option<E> error_or_none() && {
3224  if (res_().index() != 0) {
3225  if constexpr (std::is_void_v<E>) {
3226  return option<E>{std::in_place};
3227  } else {
3228  return option<E>{std::in_place, std::move(*this).res_()[index<1>]};
3229  }
3230  } else {
3231  return option<E>{};
3232  }
3233  }
3234 
3235  /// @brief Constructs a new ok value in place into the @ref result
3236  ///
3237  /// @details
3238  /// The value previously contained in the @ref result, ok or error, is
3239  /// destroyed in place. The new ok value is then constructed in place
3240  /// as if by placement new.
3241  ///
3242  /// ## Example
3243  /// ```
3244  /// result<std::string, int> res1{in_place_error, 42};
3245  /// result<std::string, int> res2{""};
3246  ///
3247  /// res1.emplace(5, 'a');
3248  /// res2.emplace(5, 'a');
3249  ///
3250  /// assert(res1.is_ok());
3251  /// assert(*res1 == "aaaaa");
3252  ///
3253  /// assert(res2.is_ok());
3254  /// assert(*res2 == "aaaaa");
3255  /// ```
3256  template <typename... Args>
3257  constexpr reference emplace(Args&&... args) {
3258  return res_().template emplace<0>(std::forward<Args>(args)...);
3259  }
3260 
3261  /// @brief Constructs a new ok value in place into the @ref result
3262  ///
3263  /// @details
3264  /// The value previously contained in the @ref result, ok or error, is
3265  /// destroyed in place. The new ok value is then constructed in place
3266  /// as if by placement new.
3267  ///
3268  /// ## Example
3269  /// ```
3270  /// result<std::vector<int>, int> res1{in_place_error, 42};
3271  /// result<std::vector<int>, int> res2{};
3272  ///
3273  /// res1.emplace({1, 2, 3, 4, 5});
3274  /// res2.emplace({1, 2, 3, 4, 5});
3275  ///
3276  /// assert(res1.is_ok());
3277  /// assert(res1->size() == 5);
3278  ///
3279  /// assert(res2.is_ok());
3280  /// assert(res2->size() == 5);
3281  /// ```
3282  template <typename U, typename... Args>
3283  constexpr reference emplace(std::initializer_list<U> ilist, Args&&... args) {
3284  return res_().template emplace<0>(ilist, std::forward<Args>(args)...);
3285  }
3286 
3287  /// @brief Constructs a new error value in place into the @ref result
3288  ///
3289  /// @details
3290  /// The value previously contained in the @ref result, ok or error, is
3291  /// destroyed in place. The new error value is then constructed in place
3292  /// as if by placement new.
3293  ///
3294  /// ## Example
3295  /// ```
3296  /// result<int, std::string> res1{42};
3297  /// result<int, std::string> res2{in_place_error, ""};
3298  ///
3299  /// res1.emplace_error(5, 'a');
3300  /// res2.emplace_error(5, 'a');
3301  ///
3302  /// assert(res1.is_error());
3303  /// assert(res1.error() == "aaaaa");
3304  ///
3305  /// assert(res2.is_error());
3306  /// assert(res2.error() == "aaaaa");
3307  /// ```
3308  template <typename... Args>
3309  constexpr error_reference emplace_error(Args&&... args) {
3310  return res_().template emplace<1>(std::forward<Args>(args)...);
3311  }
3312 
3313  /// @brief Constructs a new error value in place into the @ref result
3314  ///
3315  /// @details
3316  /// The value previously contained in the @ref result, ok or error, is
3317  /// destroyed in place. The new error value is then constructed in place
3318  /// as if by placement new.
3319  ///
3320  /// ## Example
3321  /// ```
3322  /// result<int, std::vector<int>> res1{42};
3323  /// result<int, std::vector<int>> res2{in_place_error};
3324  ///
3325  /// res1.emplace_error({1, 2, 3, 4, 5});
3326  /// res2.emplace_error({1, 2, 3, 4, 5});
3327  ///
3328  /// assert(res1.is_error());
3329  /// assert(res1.error().size() == 5);
3330  ///
3331  /// assert(res2.is_error());
3332  /// assert(res2.error().size() == 5);
3333  /// ```
3334  template <typename U, typename... Args>
3335  constexpr error_reference emplace_error(std::initializer_list<U> ilist,
3336  Args&&... args) {
3337  return res_().template emplace<1>(ilist, std::forward<Args>(args)...);
3338  }
3339 
3340  /// @brief Invokes a visitor witht he contained value
3341  ///
3342  /// @details
3343  /// This function treats a @ref result as if it was a @ref variant of
3344  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3345  /// value, that value is passed to the visitor. If the @ref result contains
3346  /// an error, the error is passed to the visitor. When either `T` or `E`
3347  /// are `void`, an instance of @ref void_t is passed instead.
3348  ///
3349  /// Note that the @ref overload function can be helpful for defining a
3350  /// visiotr inline.
3351  ///
3352  /// ## Example
3353  /// ```
3354  /// result<int, std::string> res1{42};
3355  /// result<int, std::string> res2{in_place_error, "oh no"};
3356  ///
3357  /// res1.visit(overload([](int ok_val) {
3358  /// assert(ok_val == 42);
3359  /// }, [](std::string& err_val) {
3360  /// assert(false);
3361  /// }));
3362  ///
3363  /// res2.visit(overload([](int ok_val) {
3364  /// assert(false);
3365  /// }, [](std::string& err_val) {
3366  /// assert(err_val == "oh no");
3367  /// }));
3368  /// ```
3369  template <typename V>
3370  constexpr
3371 #ifndef DOXYGEN
3372  decltype(auto)
3373 #else
3374  DEDUCED
3375 #endif
3376  visit(V&& visitor) & {
3377  return res_().visit(std::forward<V>(visitor));
3378  }
3379 
3380  /// @brief Invokes a visitor witht he contained value
3381  ///
3382  /// @details
3383  /// This function treats a @ref result as if it was a @ref variant of
3384  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3385  /// value, that value is passed to the visitor. If the @ref result contains
3386  /// an error, the error is passed to the visitor. When either `T` or `E`
3387  /// are `void`, an instance of @ref void_t is passed instead.
3388  ///
3389  /// Note that the @ref overload function can be helpful for defining a
3390  /// visiotr inline.
3391  ///
3392  /// ## Example
3393  /// ```
3394  /// const result<int, std::string> res1{42};
3395  /// const result<int, std::string> res2{in_place_error, "oh no"};
3396  ///
3397  /// res1.visit(overload([](int ok_val) {
3398  /// assert(ok_val == 42);
3399  /// }, [](const std::string& err_val) {
3400  /// assert(false);
3401  /// }));
3402  ///
3403  /// res2.visit(overload([](int ok_val) {
3404  /// assert(false);
3405  /// }, [](const std::string& err_val) {
3406  /// assert(err_val == "oh no");
3407  /// }));
3408  /// ```
3409  template <typename V>
3410  constexpr
3411 #ifndef DOXYGEN
3412  decltype(auto)
3413 #else
3414  DEDUCED
3415 #endif
3416  visit(V&& visitor) const& {
3417  return res_().visit(std::forward<V>(visitor));
3418  }
3419 
3420  /// @brief Invokes a visitor witht he contained value
3421  ///
3422  /// @details
3423  /// This function treats a @ref result as if it was a @ref variant of
3424  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3425  /// value, that value is passed to the visitor. If the @ref result contains
3426  /// an error, the error is passed to the visitor. When either `T` or `E`
3427  /// are `void`, an instance of @ref void_t is passed instead.
3428  ///
3429  /// Note that the @ref overload function can be helpful for defining a
3430  /// visiotr inline.
3431  ///
3432  /// ## Example
3433  /// ```
3434  /// result<int, std::string> res1{42};
3435  /// result<int, std::string> res2{in_place_error, "oh no"};
3436  ///
3437  /// std::move(res1).visit(overload([](int ok_val) {
3438  /// assert(ok_val == 42);
3439  /// }, [](std::string err_val) {
3440  /// assert(false);
3441  /// }));
3442  ///
3443  /// std::move(res2).visit(overload([](int ok_val) {
3444  /// assert(false);
3445  /// }, [](std::string err_val) {
3446  /// assert(err_val == "oh no");
3447  /// }));
3448  /// ```
3449  template <typename V>
3450  constexpr
3451 #ifndef DOXYGEN
3452  decltype(auto)
3453 #else
3454  DEDUCED
3455 #endif
3456  visit(V&& visitor) && {
3457  return std::move(*this).res_().visit(std::forward<V>(visitor));
3458  }
3459 
3460  /// @brief Invokes a visitor witht he contained value
3461  ///
3462  /// @details
3463  /// This function treats a @ref result as if it was a @ref variant of
3464  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3465  /// value, that value is passed to the visitor. If the @ref result contains
3466  /// an error, the error is passed to the visitor. When either `T` or `E`
3467  /// are `void`, an instance of @ref void_t is passed instead.
3468  ///
3469  /// Note that the @ref overload function can be helpful for defining a
3470  /// visiotr inline.
3471  ///
3472  /// ## Example
3473  /// ```
3474  /// const result<int, std::string> res1{42};
3475  /// const result<int, std::string> res2{in_place_error, "oh no"};
3476  ///
3477  /// std::move(res1).visit(overload([](int ok_val) {
3478  /// assert(ok_val == 42);
3479  /// }, [](std::string err_val) {
3480  /// assert(false);
3481  /// }));
3482  ///
3483  /// std::move(res2).visit(overload([](int ok_val) {
3484  /// assert(false);
3485  /// }, [](std::string err_val) {
3486  /// assert(err_val == "oh no");
3487  /// }));
3488  /// ```
3489  template <typename V>
3490  constexpr
3491 #ifndef DOXYGEN
3492  decltype(auto)
3493 #else
3494  DEDUCED
3495 #endif
3496  visit(V&& visitor) const&& {
3497  return std::move(*this).res_().visit(std::forward<V>(visitor));
3498  }
3499 
3500  /// @brief Invokes a visitor with the contained value and meta data
3501  ///
3502  /// @details
3503  /// This function treats a @ref result as if it was a @ref variant of
3504  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3505  /// value, that value is passed to the visitor. If the @ref result contains
3506  /// an error, the error is passed to the visitor. When either `T` or `E`
3507  /// are `void`, an instance of @ref void_t is passed instead.
3508  ///
3509  /// Unlike @ref visit, this function also passes an extra meta data value
3510  /// when invoking the visitor. This meta data object provides `constexpr`
3511  /// information about the type and index of the value being visited. The ok
3512  /// value has index 0 and the error value has index 1. This object has the
3513  /// the API shown below.
3514  ///
3515  /// ```
3516  /// struct alternative_info {
3517  /// // index of the alternative (ok == 0, error == 1)
3518  /// static inline constexpr size_t index = ...;
3519  ///
3520  /// // type of the alternative (ok == T, error == E)
3521  /// using type = ...;
3522  ///
3523  /// // helper function for forwarding non-const alternative values
3524  /// // without needing to provide a template argument.
3525  /// static constexpr decltype(auto) forward(...);
3526  /// }
3527  /// ```
3528  ///
3529  /// Note that the @ref overload function can be helpful for defining a
3530  /// visitor inline.
3531  ///
3532  /// ## Example
3533  /// ```
3534  /// result<int, std::string> res1{42};
3535  /// result<int, std::string> res2{in_place_error, "oh no"};
3536  ///
3537  /// res1.visit_informed([](auto&& value, auto info) {
3538  /// if constexpr (info.index == 0) { // ok
3539  /// assert(value == 42);
3540  /// } else if constexpr (info.index == 1) { // error
3541  /// assert(false);
3542  /// }
3543  /// });
3544  ///
3545  /// res2.visit_informed([](auto&& value, auto info) {
3546  /// if constexpr (info.index == 0) { // ok
3547  /// assert(false);
3548  /// } else if constexpr (info.index == 1) { // error
3549  /// assert(value == "oh no");
3550  /// }
3551  /// });
3552  /// ```
3553  template <typename V>
3554  constexpr
3555 #ifndef DOXYGEN
3556  decltype(auto)
3557 #else
3558  DEDUCED
3559 #endif
3560  visit_informed(V&& visitor) & {
3561  return res_().visit_informed(std::forward<V>(visitor));
3562  }
3563 
3564  /// @brief Invokes a visitor with the contained value and meta data
3565  ///
3566  /// @details
3567  /// This function treats a @ref result as if it was a @ref variant of
3568  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3569  /// value, that value is passed to the visitor. If the @ref result contains
3570  /// an error, the error is passed to the visitor. When either `T` or `E`
3571  /// are `void`, an instance of @ref void_t is passed instead.
3572  ///
3573  /// Unlike @ref visit, this function also passes an extra meta data value
3574  /// when invoking the visitor. This meta data object provides `constexpr`
3575  /// information about the type and index of the value being visited. The ok
3576  /// value has index 0 and the error value has index 1. This object has the
3577  /// the API shown below.
3578  ///
3579  /// ```
3580  /// struct alternative_info {
3581  /// // index of the alternative (ok == 0, error == 1)
3582  /// static inline constexpr size_t index = ...;
3583  ///
3584  /// // type of the alternative (ok == T, error == E)
3585  /// using type = ...;
3586  ///
3587  /// // helper function for forwarding non-const alternative values
3588  /// // without needing to provide a template argument.
3589  /// static constexpr decltype(auto) forward(...);
3590  /// }
3591  /// ```
3592  ///
3593  /// Note that the @ref overload function can be helpful for defining a
3594  /// visitor inline.
3595  ///
3596  /// ## Example
3597  /// ```
3598  /// const result<int, std::string> res1{42};
3599  /// const result<int, std::string> res2{in_place_error, "oh no"};
3600  ///
3601  /// res1.visit_informed([](auto&& value, auto info) {
3602  /// if constexpr (info.index == 0) { // ok
3603  /// assert(value == 42);
3604  /// } else if constexpr (info.index == 1) { // error
3605  /// assert(false);
3606  /// }
3607  /// });
3608  ///
3609  /// res2.visit_informed([](auto&& value, auto info) {
3610  /// if constexpr (info.index == 0) { // ok
3611  /// assert(false);
3612  /// } else if constexpr (info.index == 1) { // error
3613  /// assert(value == "oh no");
3614  /// }
3615  /// });
3616  /// ```
3617  template <typename V>
3618  constexpr
3619 #ifndef DOXYGEN
3620  decltype(auto)
3621 #else
3622  DEDUCED
3623 #endif
3624  visit_informed(V&& visitor) const& {
3625  return res_().visit_informed(std::forward<V>(visitor));
3626  }
3627 
3628  /// @brief Invokes a visitor with the contained value and meta data
3629  ///
3630  /// @details
3631  /// This function treats a @ref result as if it was a @ref variant of
3632  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3633  /// value, that value is passed to the visitor. If the @ref result contains
3634  /// an error, the error is passed to the visitor. When either `T` or `E`
3635  /// are `void`, an instance of @ref void_t is passed instead.
3636  ///
3637  /// Unlike @ref visit, this function also passes an extra meta data value
3638  /// when invoking the visitor. This meta data object provides `constexpr`
3639  /// information about the type and index of the value being visited. The ok
3640  /// value has index 0 and the error value has index 1. This object has the
3641  /// the API shown below.
3642  ///
3643  /// ```
3644  /// struct alternative_info {
3645  /// // index of the alternative (ok == 0, error == 1)
3646  /// static inline constexpr size_t index = ...;
3647  ///
3648  /// // type of the alternative (ok == T, error == E)
3649  /// using type = ...;
3650  ///
3651  /// // helper function for forwarding non-const alternative values
3652  /// // without needing to provide a template argument.
3653  /// static constexpr decltype(auto) forward(...);
3654  /// }
3655  /// ```
3656  ///
3657  /// Note that the @ref overload function can be helpful for defining a
3658  /// visitor inline.
3659  ///
3660  /// ## Example
3661  /// ```
3662  /// result<int, std::string> res1{42};
3663  /// result<int, std::string> res2{in_place_error, "oh no"};
3664  ///
3665  /// std::move(res1).visit_informed([](auto&& value, auto info) {
3666  /// if constexpr (info.index == 0) { // ok
3667  /// assert(value == 42);
3668  /// } else if constexpr (info.index == 1) { // error
3669  /// assert(false);
3670  /// }
3671  /// });
3672  ///
3673  /// std::move(res2).visit_informed([](auto&& value, auto info) {
3674  /// if constexpr (info.index == 0) { // ok
3675  /// assert(false);
3676  /// } else if constexpr (info.index == 1) { // error
3677  /// assert(value == "oh no");
3678  /// }
3679  /// });
3680  /// ```
3681  template <typename V>
3682  constexpr
3683 #ifndef DOXYGEN
3684  decltype(auto)
3685 #else
3686  DEDUCED
3687 #endif
3688  visit_informed(V&& visitor) && {
3689  return std::move(*this).res_().visit_informed(std::forward<V>(visitor));
3690  }
3691 
3692  /// @brief Invokes a visitor with the contained value and meta data
3693  ///
3694  /// @details
3695  /// This function treats a @ref result as if it was a @ref variant of
3696  /// `T` and `E` (i.e. `variant<T, E>`). If the @ref result contians an ok
3697  /// value, that value is passed to the visitor. If the @ref result contains
3698  /// an error, the error is passed to the visitor. When either `T` or `E`
3699  /// are `void`, an instance of @ref void_t is passed instead.
3700  ///
3701  /// Unlike @ref visit, this function also passes an extra meta data value
3702  /// when invoking the visitor. This meta data object provides `constexpr`
3703  /// information about the type and index of the value being visited. The ok
3704  /// value has index 0 and the error value has index 1. This object has the
3705  /// the API shown below.
3706  ///
3707  /// ```
3708  /// struct alternative_info {
3709  /// // index of the alternative (ok == 0, error == 1)
3710  /// static inline constexpr size_t index = ...;
3711  ///
3712  /// // type of the alternative (ok == T, error == E)
3713  /// using type = ...;
3714  ///
3715  /// // helper function for forwarding non-const alternative values
3716  /// // without needing to provide a template argument.
3717  /// static constexpr decltype(auto) forward(...);
3718  /// }
3719  /// ```
3720  ///
3721  /// Note that the @ref overload function can be helpful for defining a
3722  /// visitor inline.
3723  ///
3724  /// ## Example
3725  /// ```
3726  /// const result<int, std::string> res1{42};
3727  /// const result<int, std::string> res2{in_place_error, "oh no"};
3728  ///
3729  /// std::move(res1).visit_informed([](auto&& value, auto info) {
3730  /// if constexpr (info.index == 0) { // ok
3731  /// assert(value == 42);
3732  /// } else if constexpr (info.index == 1) { // error
3733  /// assert(false);
3734  /// }
3735  /// });
3736  ///
3737  /// std::move(res2).visit_informed([](auto&& value, auto info) {
3738  /// if constexpr (info.index == 0) { // ok
3739  /// assert(false);
3740  /// } else if constexpr (info.index == 1) { // error
3741  /// assert(value == "oh no");
3742  /// }
3743  /// });
3744  /// ```
3745  template <typename V>
3746  constexpr
3747 #ifndef DOXYGEN
3748  decltype(auto)
3749 #else
3750  DEDUCED
3751 #endif
3752  visit_informed(V&& visitor) const&& {
3753  return std::move(*this).res_().visit_informed(std::forward<V>(visitor));
3754  }
3755 
3756  /// @brief Swaps two @ref result instances
3757  ///
3758  /// @details
3759  /// If both @ref result instances contain an ok value or both contain an
3760  /// error value, the values are swapped directly. If the two @ref result
3761  /// instances do not contain the same kind of value, the values are moved
3762  /// out of the @ref results temporarily, the old values are destroyed, and
3763  /// new values a move constructed in to the opposite @ref result.
3764  ///
3765  /// ## Example
3766  /// ```
3767  /// result<int, std::string> res1{42};
3768  /// result<int, std::string> res2{in_place_error, "oh no"};
3769  ///
3770  /// res1.swap(res2);
3771  ///
3772  /// assert(res1.is_error());
3773  /// assert(res1.error() == "oh no");
3774  ///
3775  /// assert(res2.is_ok());
3776  /// assert(*res2 == 42);
3777  /// ```
3778  constexpr void swap(result& other)
3779 #ifndef DOXYGEN
3780  noexcept(std::is_nothrow_swappable_v<variant<T, E>>)
3781 #else
3783 #endif
3784  {
3785  res_().swap(other.res_);
3786  }
3787 };
3788 
3789 /// @relates result
3790 /// @brief Gets a @ref result value by index, as if it were a @ref variant
3791 ///
3792 /// @details
3793 /// This function is provided to make @ref result generically compatible with
3794 /// @ref variant. This function treats `result<T, E>` as if it were
3795 /// `variant<T, E>`, where index 0 is `T` and index 1 is `E`.
3796 ///
3797 /// ## Example
3798 /// ```
3799 /// result<int, std::string> res1{42};
3800 /// result<int, std::string> res2{in_place_error, "oh no"};
3801 ///
3802 /// assert(get<0>(res1) == 42);
3803 /// assert(get<1>(res2) == "oh no");
3804 /// ```
3805 ///
3806 /// @tparam IDX The "alternative" index
3807 ///
3808 /// @param res The @ref result to access
3809 ///
3810 /// @return A reference to the accessed "alternative"
3811 ///
3812 /// @throws bad_result_access Thrown if the @ref result does not contain the
3813 /// matching index.
3814 template <size_t IDX, typename T, typename E>
3815 constexpr
3816 #ifndef DOXYGEN
3817  typename detail::traits<detail::select_t<IDX, T, E>>::reference
3818 #else
3819  REFERENCE
3820 #endif
3821  get(result<T, E>& res) {
3822  return get<IDX>(res.res_);
3823 }
3824 
3825 /// @relates result
3826 /// @brief Gets a @ref result value by index, as if it were a @ref variant
3827 ///
3828 /// @details
3829 /// This function is provided to make @ref result generically compatible with
3830 /// @ref variant. This function treats `result<T, E>` as if it were
3831 /// `variant<T, E>`, where index 0 is `T` and index 1 is `E`.
3832 ///
3833 /// ## Example
3834 /// ```
3835 /// const result<int, std::string> res1{42};
3836 /// const result<int, std::string> res2{in_place_error, "oh no"};
3837 ///
3838 /// assert(get<0>(res1) == 42);
3839 /// assert(get<1>(res2) == "oh no");
3840 /// ```
3841 ///
3842 /// @tparam IDX The "alternative" index
3843 ///
3844 /// @param res The @ref result to access
3845 ///
3846 /// @return A const reference to the accessed "alternative"
3847 ///
3848 /// @throws bad_result_access Thrown if the @ref result does not contain the
3849 /// matching index.
3850 template <size_t IDX, typename T, typename E>
3851 constexpr
3852 #ifndef DOXYGEN
3853  typename detail::traits<detail::select_t<IDX, T, E>>::const_reference
3854 #else
3856 #endif
3857  get(const result<T, E>& res) {
3858  return get<IDX>(res.res_);
3859 }
3860 
3861 /// @relates result
3862 /// @brief Gets a @ref result value by index, as if it were a @ref variant
3863 ///
3864 /// @details
3865 /// This function is provided to make @ref result generically compatible with
3866 /// @ref variant. This function treats `result<T, E>` as if it were
3867 /// `variant<T, E>`, where index 0 is `T` and index 1 is `E`.
3868 ///
3869 /// ## Example
3870 /// ```
3871 /// result<int, std::string> res1{42};
3872 /// result<int, std::string> res2{in_place_error, "oh no"};
3873 ///
3874 /// assert(get<0>(std::move(res1)) == 42);
3875 /// assert(get<1>(std::move(res2)) == "oh no");
3876 /// ```
3877 ///
3878 /// @tparam IDX The "alternative" index
3879 ///
3880 /// @param res The @ref result to access
3881 ///
3882 /// @return An rvalue of the accessed "alternative"
3883 ///
3884 /// @throws bad_result_access Thrown if the @ref result does not contain the
3885 /// matching index.
3886 template <size_t IDX, typename T, typename E>
3887 constexpr
3888 #ifndef DOXYGEN
3889  typename detail::traits<detail::select_t<IDX, T, E>>::rvalue_reference
3890 #else
3892 #endif
3893  // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
3894  get(result<T, E>&& res) {
3895  return get<IDX>(std::move(res.res_));
3896 }
3897 
3898 /// @relates result
3899 /// @brief Gets a @ref result value by index, as if it were a @ref variant
3900 ///
3901 /// @details
3902 /// This function is provided to make @ref result generically compatible with
3903 /// @ref variant. This function treats `result<T, E>` as if it were
3904 /// `variant<T, E>`, where index 0 is `T` and index 1 is `E`.
3905 ///
3906 /// ## Example
3907 /// ```
3908 /// const result<int, std::string> res1{42};
3909 /// const result<int, std::string> res2{in_place_error, "oh no"};
3910 ///
3911 /// assert(get<0>(std::move(res1)) == 42);
3912 /// assert(get<1>(std::move(res2)) == "oh no");
3913 /// ```
3914 ///
3915 /// @tparam IDX The "alternative" index
3916 ///
3917 /// @param res The @ref result to access
3918 ///
3919 /// @return A const rvalue of the accessed "alternative"
3920 ///
3921 /// @throws bad_result_access Thrown if the @ref result does not contain the
3922 /// matching index.
3923 template <size_t IDX, typename T, typename E>
3924 constexpr
3925 #ifndef DOXYGEN
3926  typename detail::traits<detail::select_t<IDX, T, E>>::const_rvalue_reference
3927 #else
3929 #endif
3930  get(const result<T, E>&& res) {
3931  return get<IDX>(std::move(res.res_));
3932 }
3933 
3934 /// @relates result
3935 /// @brief Gets a @ref result value by type, as if it were a @ref variant
3936 ///
3937 /// @details
3938 /// This fucntion is provided to make @ref result generically compatible with
3939 /// @ref variant. This function treats `result<T, E>` as if it were
3940 /// `variant<T, E>`.
3941 ///
3942 /// This function only participates in overload resolution if `T` and `E` are
3943 /// distinct types, in order to avoid ambiguity.
3944 ///
3945 /// ## Example
3946 /// ```
3947 /// result<int, std::string> res1{42};
3948 /// result<int, std::string> res2{in_place_error, "oh no"};
3949 ///
3950 /// assert(get<int>(res1) == 42);
3951 /// assert(get<std::string>(res2) == "oh no");
3952 /// ```
3953 ///
3954 /// @tparam U The "alternative" type
3955 ///
3956 /// @param res The @ref result to access
3957 ///
3958 /// @return A reference to the accessed "alternative"
3959 ///
3960 /// @throws bad_result_access Thrown if the @ref result does not contain the
3961 /// matching index.
3962 template <typename U, typename T, typename E>
3963 #ifndef DOXYGEN
3964  requires(std::is_same_v<U, T> || std::is_same_v<U, E>)
3965 #endif
3966 constexpr
3967 #ifndef DOXYGEN
3968  typename detail::traits<U>::reference
3969 #else
3970  REFERENCE
3971 #endif
3972  get(result<T, E>& res) {
3973  return get<U>(res.res_);
3974 }
3975 
3976 /// @relates result
3977 /// @brief Gets a @ref result value by type, as if it were a @ref variant
3978 ///
3979 /// @details
3980 /// This fucntion is provided to make @ref result generically compatible with
3981 /// @ref variant. This function treats `result<T, E>` as if it were
3982 /// `variant<T, E>`.
3983 ///
3984 /// This function only participates in overload resolution if `T` and `E` are
3985 /// distinct types, in order to avoid ambiguity.
3986 ///
3987 /// ## Example
3988 /// ```
3989 /// const result<int, std::string> res1{42};
3990 /// const result<int, std::string> res2{in_place_error, "oh no"};
3991 ///
3992 /// assert(get<int>(res1) == 42);
3993 /// assert(get<std::string>(res2) == "oh no");
3994 /// ```
3995 ///
3996 /// @tparam U The "alternative" type
3997 ///
3998 /// @param res The @ref result to access
3999 ///
4000 /// @return A const reference to the accessed "alternative"
4001 ///
4002 /// @throws bad_result_access Thrown if the @ref result does not contain the
4003 /// matching index.
4004 template <typename U, typename T, typename E>
4005 #ifndef DOXYGEN
4006  requires(std::is_same_v<U, T> || std::is_same_v<U, E>)
4007 #endif
4008 constexpr
4009 #ifndef DOXYGEN
4010  typename detail::traits<U>::const_reference
4011 #else
4013 #endif
4014  get(const result<T, E>& res) {
4015  return get<U>(res.res_);
4016 }
4017 
4018 /// @relates result
4019 /// @brief Gets a @ref result value by type, as if it were a @ref variant
4020 ///
4021 /// @details
4022 /// This fucntion is provided to make @ref result generically compatible with
4023 /// @ref variant. This function treats `result<T, E>` as if it were
4024 /// `variant<T, E>`.
4025 ///
4026 /// This function only participates in overload resolution if `T` and `E` are
4027 /// distinct types, in order to avoid ambiguity.
4028 ///
4029 /// ## Example
4030 /// ```
4031 /// result<int, std::string> res1{42};
4032 /// result<int, std::string> res2{in_place_error, "oh no"};
4033 ///
4034 /// assert(get<int>(std::move(res1)) == 42);
4035 /// assert(get<std::string>(std::move(res2)) == "oh no");
4036 /// ```
4037 ///
4038 /// @tparam U The "alternative" type
4039 ///
4040 /// @param res The @ref result to access
4041 ///
4042 /// @return An rvalue of the accessed "alternative"
4043 ///
4044 /// @throws bad_result_access Thrown if the @ref result does not contain the
4045 /// matching index.
4046 template <typename U, typename T, typename E>
4047 #ifndef DOXYGEN
4048  requires(std::is_same_v<U, T> || std::is_same_v<U, E>)
4049 #endif
4050 constexpr
4051 #ifndef DOXYGEN
4052  typename detail::traits<U>::rvalue_reference
4053 #else
4055 #endif
4056  // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
4057  get(result<T, E>&& res) {
4058  return get<U>(std::move(res.res_));
4059 }
4060 
4061 /// @relates result
4062 /// @brief Gets a @ref result value by type, as if it were a @ref variant
4063 ///
4064 /// @details
4065 /// This fucntion is provided to make @ref result generically compatible with
4066 /// @ref variant. This function treats `result<T, E>` as if it were
4067 /// `variant<T, E>`.
4068 ///
4069 /// This function only participates in overload resolution if `T` and `E` are
4070 /// distinct types, in order to avoid ambiguity.
4071 ///
4072 /// ## Example
4073 /// ```
4074 /// const result<int, std::string> res1{42};
4075 /// const result<int, std::string> res2{in_place_error, "oh no"};
4076 ///
4077 /// assert(get<int>(std::move(res1)) == 42);
4078 /// assert(get<std::string>(std::move(res2)) == "oh no");
4079 /// ```
4080 ///
4081 /// @tparam U The "alternative" type
4082 ///
4083 /// @param res The @ref result to access
4084 ///
4085 /// @return A const rvalue of the accessed "alternative"
4086 ///
4087 /// @throws bad_result_access Thrown if the @ref result does not contain the
4088 /// matching index.
4089 template <typename U, typename T, typename E>
4090 #ifndef DOXYGEN
4091  requires(std::is_same_v<U, T> || std::is_same_v<U, E>)
4092 #endif
4093 constexpr
4094 #ifndef DOXYGEN
4095  typename detail::traits<U>::const_rvalue_reference
4096 #else
4098 #endif
4099  get(const result<T, E>&& res) {
4100  return get<U>(std::move(res.res_));
4101 }
4102 
4103 /// @relates result
4104 /// @brief Compares two @ref result instances for equality
4105 ///
4106 /// @details
4107 /// Returns true if both @ref result instances either both contain ok values or
4108 /// both contain error values, and the values compare equal.
4109 ///
4110 /// ## Example
4111 /// ```
4112 /// result<int, std::string> res1{42};
4113 /// result<unsigned int, const char*> res2{42};
4114 ///
4115 /// assert(res1 == res2);
4116 /// ```
4117 template <typename T, typename E, typename U, typename V>
4118 #ifndef DOXYGEN
4119  requires(std::is_void_v<T> == std::is_void_v<U> &&
4120  std::is_void_v<E> == std::is_void_v<V>)
4121 #endif
4122 constexpr bool operator==(const result<T, E>& lhs, const result<U, V>& rhs) {
4123  if (lhs.has_value()) {
4124  if constexpr (std::is_void_v<T>) {
4125  return rhs.has_value();
4126  } else {
4127  if (rhs.has_value()) {
4128  return *lhs == *rhs;
4129  } else {
4130  return false;
4131  }
4132  }
4133  } else {
4134  if constexpr (std::is_void_v<E>) {
4135  return !rhs.has_value();
4136  } else {
4137  if (rhs.has_value()) {
4138  return false;
4139  } else {
4140  return lhs.error() == rhs.error();
4141  }
4142  }
4143  }
4144 }
4145 
4146 /// @relates result
4147 /// @brief Compares a @ref result with a plain value for equality
4148 ///
4149 /// @details
4150 /// This function return true if the @ref result contains an ok value and the
4151 /// ok value compares equal with the plain value.
4152 ///
4153 /// ## Example
4154 /// ```
4155 /// result<int, std::string> res1{42};
4156 /// result<int, std::string> res2{in_place_error, "oh no"};
4157 ///
4158 /// assert(res1 == 42);
4159 /// assert(res2 != 42);
4160 /// ```
4161 template <typename T, typename E, typename U>
4162 constexpr bool operator==(const result<T, E>& lhs, const U& rhs) {
4163  return lhs.has_value() && *lhs == rhs;
4164 }
4165 
4166 /// @relates result
4167 /// @brief Compares a @ref result with a plain value for equality
4168 ///
4169 /// @details
4170 /// This function return true if the @ref result contains an ok value and the
4171 /// ok value compares equal with the plain value.
4172 ///
4173 /// ## Example
4174 /// ```
4175 /// result<int, std::string> res1{42};
4176 /// result<int, std::string> res2{in_place_error, "oh no"};
4177 ///
4178 /// assert(42 == res1);
4179 /// assert(42 != res2);
4180 /// ```
4181 template <typename T, typename E, typename U>
4182 constexpr bool operator==(const U& lhs, const result<T, E>& rhs) {
4183  return rhs.has_value() && lhs == *rhs;
4184 }
4185 
4186 /// @relates result
4187 /// @brief Swaps two @ref result instances
4188 ///
4189 /// @details
4190 /// If both @ref result instances contain an ok value or both contain an
4191 /// error value, the values are swapped directly. If the two @ref result
4192 /// instances do not contain the same kind of value, the values are moved
4193 /// out of the @ref results temporarily, the old values are destroyed, and
4194 /// new values a move constructed in to the opposite @ref result.
4195 ///
4196 /// ## Example
4197 /// ```
4198 /// result<int, std::string> res1{42};
4199 /// result<int, std::string> res2{in_place_error, "oh no"};
4200 ///
4201 /// swap(res1, res2);
4202 ///
4203 /// assert(res1.is_error());
4204 /// assert(res1.error() == "oh no");
4205 ///
4206 /// assert(res2.is_ok());
4207 /// assert(*res2 == 42);
4208 /// ```
4209 template <typename T, typename E>
4210 constexpr void swap(result<T, E>& a, result<T, E>& b)
4211 #ifndef DOXYGEN
4212  noexcept(std::is_nothrow_swappable_v<variant<T, E>>)
4213 #else
4215 #endif
4216 {
4217  a.swap(b);
4218 }
4219 
4220 /// @relates result
4221 /// @brief Creates an ok valued @ref result, constructed in place
4222 ///
4223 /// @details
4224 /// Similar to STL functions like `std::make_unique` and `std::make_optional`,
4225 /// this function is provided a template argument to specify what contained
4226 /// type should be constructed, and then is passed arguments that are
4227 /// forwarded to the constructor of the contained type.
4228 ///
4229 /// ## Example
4230 /// ```
4231 /// result<std::string, void> make_string() {
4232 /// // returns a result<std::string, never> which gets converted to
4233 /// // a result<std::string, void>
4234 /// return ok<std::string>("hello");
4235 /// }
4236 /// ```
4237 template <typename T, typename... Args>
4238 constexpr result<T, never> ok(Args&&... args) {
4239  return result<T, never>{std::in_place, std::forward<Args>(args)...};
4240 }
4241 
4242 /// @relates result
4243 /// @brief Creates an ok valued @ref result, constructed in place
4244 ///
4245 /// @details
4246 /// Similar to STL functions like `std::make_unique` and `std::make_optional`,
4247 /// this function is provided a template argument to specify what contained
4248 /// type should be constructed, and then is passed arguments that are
4249 /// forwarded to the constructor of the contained type.
4250 ///
4251 /// ## Example
4252 /// ```
4253 /// result<std::vector<int>, void> make_nums() {
4254 /// // returns a result<std::vector<int>, never> which gets converted
4255 /// // to a result<std::vector<int>, void>
4256 /// return ok<std::vector<int>>({1, 2, 3, 4, 5});
4257 /// }
4258 /// ```
4259 template <typename T, typename U, typename... Args>
4260 constexpr result<T, never> ok(std::initializer_list<U> ilist, Args&&... args) {
4261  return result<T, never>{std::in_place, ilist, std::forward<Args>(args)...};
4262 }
4263 
4264 /// @relates result
4265 /// @brief Creates an error valued @ref result, constructed in place
4266 ///
4267 /// @details
4268 /// Similar to STL functions like `std::make_unique` and `std::make_optional`,
4269 /// this function is provided a template argument to specify what contained
4270 /// error type should be constructed, and then is passed arguments that are
4271 /// forwarded to the constructor of the contained error type.
4272 ///
4273 /// ## Example
4274 /// ```
4275 /// result<void, std::string> ensure_positive(int value) {
4276 /// if (value < 0) {
4277 /// return error<std::string>("value is negative");
4278 /// }
4279 /// return value;
4280 /// }
4281 /// ```
4282 template <typename E, typename... Args>
4283 constexpr result<never, E> error(Args&&... args) {
4284  return result<never, E>{in_place_error, std::forward<Args>(args)...};
4285 }
4286 
4287 /// @relates result
4288 /// @brief Creates an error valued @ref result, constructed in place
4289 ///
4290 /// @details
4291 /// Similar to STL functions like `std::make_unique` and `std::make_optional`,
4292 /// this function is provided a template argument to specify what contained
4293 /// error type should be constructed, and then is passed arguments that are
4294 /// forwarded to the constructor of the contained error type.
4295 ///
4296 /// ## Example
4297 /// ```
4298 /// result<void, std::vector<int>> ilist_error_example() {
4299 /// // returns a result<never, std::vector<int>> which gets converted
4300 /// // to a result<void, std::vector<int>>
4301 /// return error<std::vector<int>>({1, 2, 3, 4, 5});
4302 /// }
4303 /// ```
4304 template <typename E, typename U, typename... Args>
4305 constexpr result<never, E> error(std::initializer_list<U> ilist, Args&&... args) {
4306  return result<never, E>{in_place_error, ilist, std::forward<Args>(args)...};
4307 }
4308 
4309 /// @private
4310 template <typename T, typename E>
4311  requires(std::is_base_of_v<never, std::remove_cvref_t<T>> &&
4312  std::is_base_of_v<never, std::remove_cvref_t<E>>)
4313 class result<T, E> : public never {};
4314 
4315 } // namespace sumty
4316 
4317 #endif