16 #ifndef SUMTY_RESULT_HPP
17 #define SUMTY_RESULT_HPP
19 #include "sumty/detail/fwd.hpp"
20 #include "sumty/detail/traits.hpp"
21 #include "sumty/detail/utils.hpp"
22 #include "sumty/exceptions.hpp"
23 #include "sumty/option.hpp"
24 #include "sumty/utils.hpp"
25 #include "sumty/variant.hpp"
29 #include <initializer_list>
30 #include <type_traits>
87 template <
typename T,
typename E>
88 class result : variant<T, E> {
90 [[nodiscard]]
constexpr variant<T, E>& res_() &
noexcept {
91 return *
static_cast<variant<T, E>*>(
this);
94 [[nodiscard]]
constexpr const variant<T, E>& res_()
const&
noexcept {
95 return *
static_cast<
const variant<T, E>*>(
this);
98 [[nodiscard]]
constexpr variant<T, E>&& res_() && {
99 return std::move(*
static_cast<variant<T, E>*>(
this));
102 [[nodiscard]]
constexpr const variant<T, E>& res_()
const&& {
103 return std::move(*
static_cast<
const variant<T, E>*>(
this));
106 template <
typename,
typename>
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;
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;
127 using value_type = ...;
128 using reference = ...;
129 using const_reference = ...;
130 using rvalue_reference = ...;
131 using const_rvalue_reference = ...;
133 using const_pointer = ...;
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 = ...;
144 template <
typename U>
145 using rebind = result<U, E>;
147 template <
typename V>
148 using rebind_error = result<T, V>;
151 using unexpected_type = result<
never, E>;
172 CONDITIONALLY_NOEXCEPT;
203 CONDITIONALLY_NOEXCEPT;
234 CONDITIONALLY_NOEXCEPT;
253 template <
typename... Args>
255 explicit(
sizeof...(
Args) == 0)
261 : variant<T, E>(std::in_place_index<0>, std::forward<Args>(args)...) {
279 template <
typename U,
typename... Args>
281 std::initializer_list<U> init,
283 : variant<T, E>(std::in_place_index<0>, init, std::forward<Args>(args)...) {}
301 template <
typename... Args>
303 explicit(
sizeof...(
Args) == 0)
308 constexpr result(std::in_place_index_t<0> inplace, Args&&... args)
309 : variant<T, E>(inplace, std::forward<Args>(args)...) {
327 template <
typename U,
typename... Args>
328 constexpr result(std::in_place_index_t<0> inplace,
329 std::initializer_list<U> init,
331 : variant<T, E>(inplace, init, std::forward<Args>(args)...) {}
347 template <
typename... Args>
349 explicit(
sizeof...(
Args) == 0)
354 constexpr result(in_place_error_t inplace, Args&&... args)
355 : variant<T, E>(inplace, std::forward<Args>(args)...) {
372 template <
typename U,
typename... Args>
373 constexpr result(in_place_error_t inplace,
374 std::initializer_list<U> init,
376 : variant<T, E>(inplace, init, std::forward<Args>(args)...) {}
405 template <
typename U>
419 : variant<T, E>(std::in_place_index<0>, std::forward<U>(value)) {
453 template <
typename U,
typename V>
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));
508 template <
typename U,
typename V>
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));
545 CONDITIONALLY_NOEXCEPT;
589 CONDITIONALLY_NOEXCEPT;
633 CONDITIONALLY_NOEXCEPT;
659 template <
typename U>
667 if (res_().index() == 0) {
668 res_()[index<0>] = std::forward<U>(value);
670 res_().
template emplace<0>(std::forward<U>(value));
699 constexpr operator bool()
const noexcept {
return res_().index() == 0; }
712 [[nodiscard]]
constexpr bool has_value()
const noexcept {
return res_().index() == 0; }
725 [[nodiscard]]
constexpr bool is_ok()
const noexcept {
return res_().index() == 0; }
738 [[nodiscard]]
constexpr bool is_error()
const noexcept {
return res_().index() != 0; }
753 [[nodiscard]]
constexpr reference
operator*() &
noexcept {
return res_()[index<0>]; }
768 [[nodiscard]]
constexpr const_reference
operator*()
const&
noexcept {
769 return res_()[index<0>];
785 [[nodiscard]]
constexpr rvalue_reference
operator*() && {
786 return std::move(*
this).res_()[index<0>];
802 [[nodiscard]]
constexpr const_rvalue_reference
operator*()
const&& {
803 return std::move(*
this).res_()[index<0>];
819 [[nodiscard]]
constexpr pointer
operator->()
noexcept {
return &res_()[index<0>]; }
834 [[nodiscard]]
constexpr const_pointer
operator->()
const noexcept {
835 return &res_()[index<0>];
853 [[nodiscard]]
constexpr reference
value() & {
854 if (res_().index() != 0) {
855 if constexpr (std::is_void_v<E>) {
861 return res_()[index<0>];
879 [[nodiscard]]
constexpr const_reference
value()
const& {
880 if (res_().index() != 0) {
881 if constexpr (std::is_void_v<E>) {
887 return res_()[index<0>];
905 [[nodiscard]]
constexpr rvalue_reference
value() && {
906 if (res_().index() != 0) {
907 if constexpr (std::is_void_v<E>) {
911 std::move(*
this).res_()[index<1>]);
914 return std::move(*
this).res_()[index<0>];
932 [[nodiscard]]
constexpr rvalue_reference
value()
const&& {
933 if (res_().index() != 0) {
934 if constexpr (std::is_void_v<E>) {
938 std::move(*
this).res_()[index<1>]);
941 return std::move(*
this).res_()[index<0>];
957 [[nodiscard]]
constexpr error_reference
error() &
noexcept {
return res_()[index<1>]; }
972 [[nodiscard]]
constexpr error_const_reference
error()
const&
noexcept {
973 return res_()[index<1>];
989 [[nodiscard]]
constexpr error_rvalue_reference
error() && {
990 return std::move(*
this).res_()[index<1>];
1006 [[nodiscard]]
constexpr error_const_rvalue_reference
error()
const&& {
1007 return std::move(*
this).res_()[index<1>];
1030 return result<
never, E>{in_place_error, error()};
1053 return result<
never, E>{in_place_error, std::move(*
this).error()};
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>];
1078 return static_cast<value_type>(std::forward<U>(default_value));
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>];
1104 return static_cast<value_type>(std::forward<U>(default_value));
1125 template <
typename F>
1127 if (res_().index() == 0) {
1128 return res_()[index<0>];
1130 return static_cast<T>(invoke(std::forward<F>(f)));
1151 template <
typename F>
1153 if (res_().index() == 0) {
1154 return std::move(*
this).res_()[index<0>];
1156 return static_cast<T>(invoke(std::forward<F>(f)));
1175 [[nodiscard]]
constexpr reference
ok() & {
return value(); }
1192 [[nodiscard]]
constexpr const_reference
ok()
const& {
return value(); }
1209 [[nodiscard]]
constexpr rvalue_reference
ok() && {
return std::move(*
this).value(); }
1226 [[nodiscard]]
constexpr rvalue_reference
ok()
const&& {
1227 return std::move(*
this).value();
1247 template <
typename U>
1248 [[nodiscard]]
constexpr value_type
ok_or(U&& default_value)
const& {
1249 return value_or(std::forward<U>(default_value));
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));
1291 template <
typename F>
1293 return value_or_else(std::forward<F>(f));
1313 template <
typename F>
1315 return std::move(*
this).value_or_else(std::forward<F>(f));
1356 template <
typename F>
1363 if constexpr (std::is_void_v<T>) {
1364 if (res_().index() == 0) {
1365 return std::invoke(std::forward<F>(f), void_v);
1367 if constexpr (std::is_void_v<E>) {
1368 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1371 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1372 in_place_error, res_()[index<1>]};
1376 if (res_().index() == 0) {
1377 return std::invoke(std::forward<F>(f), res_()[index<0>]);
1379 if constexpr (std::is_void_v<E>) {
1380 return std::remove_cvref_t<std::invoke_result_t<F, reference>>{
1383 return std::remove_cvref_t<std::invoke_result_t<F, reference>>{
1384 in_place_error, res_()[index<1>]};
1428 template <
typename F>
1430 if constexpr (std::is_void_v<T>) {
1431 if (res_().index() == 0) {
1432 return std::invoke(std::forward<F>(f), void_v);
1434 if constexpr (std::is_void_v<E>) {
1435 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1438 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1439 in_place_error, res_()[index<1>]};
1443 if (res_().index() == 0) {
1444 return std::invoke(std::forward<F>(f), res_()[index<0>]);
1446 if constexpr (std::is_void_v<E>) {
1447 return std::remove_cvref_t<std::invoke_result_t<F, const_reference>>{
1450 return std::remove_cvref_t<std::invoke_result_t<F, const_reference>>{
1451 in_place_error, res_()[index<1>]};
1495 template <
typename F>
1497 if constexpr (std::is_void_v<T>) {
1498 if (res_().index() == 0) {
1499 return std::invoke(std::forward<F>(f), void_v);
1501 if constexpr (std::is_void_v<E>) {
1502 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1505 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1506 in_place_error, std::move(*
this).res_()[index<1>]};
1510 if (res_().index() == 0) {
1511 return std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<0>]);
1513 if constexpr (std::is_void_v<E>) {
1514 return std::remove_cvref_t<std::invoke_result_t<F, rvalue_reference>>{
1517 return std::remove_cvref_t<std::invoke_result_t<F, rvalue_reference>>{
1518 in_place_error, std::move(*
this).res_()[index<1>]};
1562 template <
typename F>
1564 if constexpr (std::is_void_v<T>) {
1565 if (res_().index() == 0) {
1566 return std::invoke(std::forward<F>(f), void_v);
1568 if constexpr (std::is_void_v<E>) {
1569 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1572 return std::remove_cvref_t<std::invoke_result_t<F,
void_t>>{
1573 in_place_error, std::move(*
this).res_()[index<1>]};
1577 if (res_().index() == 0) {
1578 return std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<0>]);
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};
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>]};
1625 template <
typename 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};
1634 return result<res_t, E>{std::in_place,
1635 std::invoke(std::forward<F>(f), void_v)};
1638 if constexpr (std::is_void_v<E>) {
1639 return result<res_t, E>{in_place_error};
1641 return result<res_t, E>{in_place_error, res_()[index<1>]};
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};
1651 return result<res_t, E>{
1652 std::in_place, std::invoke(std::forward<F>(f), res_()[index<0>])};
1655 if constexpr (std::is_void_v<E>) {
1656 return result<res_t, E>{in_place_error};
1658 return result<res_t, E>{in_place_error, res_()[index<1>]};
1697 template <
typename F>
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};
1706 return result<res_t, E>{std::in_place,
1707 std::invoke(std::forward<F>(f), void_v)};
1710 if constexpr (std::is_void_v<E>) {
1711 return result<res_t, E>{in_place_error};
1713 return result<res_t, E>{in_place_error, res_()[index<1>]};
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};
1723 return result<res_t, E>{
1724 std::in_place, std::invoke(std::forward<F>(f), res_()[index<0>])};
1727 if constexpr (std::is_void_v<E>) {
1728 return result<res_t, E>{in_place_error};
1730 return result<res_t, E>{in_place_error, res_()[index<1>]};
1769 template <
typename 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};
1778 return result<res_t, E>{std::in_place,
1779 std::invoke(std::forward<F>(f), void_v)};
1782 if constexpr (std::is_void_v<E>) {
1783 return result<res_t, E>{in_place_error};
1785 return result<res_t, E>{in_place_error,
1786 std::move(*
this).res_()[index<1>]};
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};
1796 return result<res_t, E>{
1798 std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<0>])};
1801 if constexpr (std::is_void_v<E>) {
1802 return result<res_t, E>{in_place_error};
1804 return result<res_t, E>{in_place_error,
1805 std::move(*
this).res_()[index<1>]};
1844 template <
typename F>
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};
1853 return result<res_t, E>{std::in_place,
1854 std::invoke(std::forward<F>(f), void_v)};
1857 if constexpr (std::is_void_v<E>) {
1858 return result<res_t, E>{in_place_error};
1860 return result<res_t, E>{in_place_error,
1861 std::move(*
this).res_()[index<1>]};
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};
1871 return result<res_t, E>{
1873 std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<0>])};
1876 if constexpr (std::is_void_v<E>) {
1877 return result<res_t, E>{in_place_error};
1879 return result<res_t, E>{in_place_error,
1880 std::move(*
this).res_()[index<1>]};
1918 template <
typename F>
1920 return transform(std::forward<F>(f));
1955 template <
typename F>
1956 constexpr auto map(F&& f)
const& {
1957 return transform(std::forward<F>(f));
1992 template <
typename F>
1993 constexpr auto map(F&& f) && {
1994 return std::move(*
this).transform(std::forward<F>(f));
2029 template <
typename F>
2030 constexpr auto map(F&& f)
const&& {
2031 return std::move(*
this).transform(std::forward<F>(f));
2061 template <
typename F>
2063 if (res_().index() == 0) {
2066 if constexpr (std::is_void_v<E>) {
2067 return std::invoke(std::forward<F>(f), void_v);
2069 return std::invoke(std::forward<F>(f), res_()[index<1>]);
2101 template <
typename F>
2103 if (res_().index() == 0) {
2104 return std::move(*
this);
2106 if constexpr (std::is_void_v<E>) {
2107 return std::invoke(std::forward<F>(f), void_v);
2109 return std::invoke(std::forward<F>(f), std::move(res_()[index<1>]));
2164 if constexpr (std::is_void_v<
typename T::error_type>) {
2165 using ret_t = result<
typename T::value_type, E>;
2167 return ret_t{res_()[index<0>]};
2169 if constexpr (std::is_void_v<E>) {
2170 return ret_t{in_place_error};
2172 return ret_t{in_place_error, error()};
2175 }
else if constexpr (std::is_void_v<E>) {
2178 return res_()[index<0>];
2180 return ret_t{in_place_error, error()};
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>;
2186 return ret_t{res_()[index<0>]};
2188 return ret_t{in_place_error, error()};
2190 }
else if constexpr (detail::traits<
typename T::error_type>::
2191 template is_constructible<error_const_reference>) {
2194 return res_()[index<0>];
2196 return ret_t{in_place_error, error()};
2251 if constexpr (std::is_void_v<
typename T::error_type>) {
2252 using ret_t = result<
typename T::value_type, E>;
2254 return ret_t{std::move(res_()[index<0>])};
2256 if constexpr (std::is_void_v<E>) {
2257 return ret_t{in_place_error};
2259 return ret_t{in_place_error, std::move(error())};
2262 }
else if constexpr (std::is_void_v<E>) {
2265 return std::move(res_()[index<0>]);
2267 return ret_t{in_place_error, std::move(error())};
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>;
2273 return ret_t{std::move(res_()[index<0>])};
2275 return ret_t{in_place_error, std::move(error())};
2277 }
else if constexpr (detail::traits<
typename T::error_type>::
2278 template is_constructible<error_rvalue_reference>) {
2281 return std::move(res_()[index<0>]);
2283 return ret_t{in_place_error, std::move(error())};
2327 if constexpr (detail::is_result_v<T>) {
2328 return flatten().flatten_all();
2373 if constexpr (detail::is_result_v<T>) {
2374 return std::move(*
this).flatten().flatten_all();
2376 return std::move(*
this);
2418 using ret_t = option<result<
typename T::value_type, E>>;
2420 if (res_()[index<0>].is_some()) {
2421 return ret_t{in_place, in_place, *res_()[index<0>]};
2426 return ret_t{in_place, in_place_error, error()};
2468 using ret_t = option<result<
typename T::value_type, E>>;
2470 if (res_()[index<0>].is_some()) {
2471 return ret_t{in_place, in_place, std::move(*res_()[index<0>])};
2476 return ret_t{in_place, in_place_error, std::move(error())};
2501 [[nodiscard]]
constexpr result<E, T>
invert()
const& {
2503 return result<E, T>{in_place_error, res_()[0]};
2505 return result<E, T>{in_place, error()};
2530 [[nodiscard]]
constexpr result<E, T>
invert() && {
2532 return result<E, T>{in_place_error, std::move(res_()[0])};
2534 return result<E, T>{in_place, std::move(error())};
2570 template <
typename 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};
2579 return result<T, res_t>{in_place_error,
2580 std::invoke(std::forward<F>(f), void_v)};
2583 if constexpr (std::is_void_v<T>) {
2584 return result<T, res_t>{std::in_place};
2586 return result<T, res_t>{std::in_place, res_()[index<0>]};
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};
2596 return result<T, res_t>{
2597 in_place_error, std::invoke(std::forward<F>(f), res_()[index<1>])};
2600 if constexpr (std::is_void_v<T>) {
2601 return result<T, res_t>{std::in_place};
2603 return result<T, res_t>{std::in_place, res_()[index<0>]};
2641 template <
typename F>
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};
2650 return result<T, res_t>{in_place_error,
2651 std::invoke(std::forward<F>(f), void_v)};
2654 if constexpr (std::is_void_v<T>) {
2655 return result<T, res_t>{std::in_place};
2657 return result<T, res_t>{std::in_place, res_()[index<0>]};
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};
2667 return result<T, res_t>{
2668 in_place_error, std::invoke(std::forward<F>(f), res_()[index<1>])};
2671 if constexpr (std::is_void_v<T>) {
2672 return result<T, res_t>{std::in_place};
2674 return result<T, res_t>{std::in_place, res_()[index<0>]};
2712 template <
typename 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};
2721 return result<T, res_t>{in_place_error,
2722 std::invoke(std::forward<F>(f), void_v)};
2725 if constexpr (std::is_void_v<T>) {
2726 return result<T, res_t>{std::in_place};
2728 return result<T, res_t>{std::in_place,
2729 std::move(*
this).res_()[index<0>]};
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};
2739 return result<T, res_t>{
2741 std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<1>])};
2744 if constexpr (std::is_void_v<T>) {
2745 return result<T, res_t>{std::in_place};
2747 return result<T, res_t>{std::in_place,
2748 std::move(*
this).res_()[index<0>]};
2786 template <
typename F>
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};
2795 return result<T, res_t>{in_place_error,
2796 std::invoke(std::forward<F>(f), void_v)};
2799 if constexpr (std::is_void_v<T>) {
2800 return result<T, res_t>{std::in_place};
2802 return result<T, res_t>{std::in_place,
2803 std::move(*
this).res_()[index<0>]};
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};
2813 return result<T, res_t>{
2815 std::invoke(std::forward<F>(f), std::move(*
this).res_()[index<1>])};
2818 if constexpr (std::is_void_v<T>) {
2819 return result<T, res_t>{std::in_place};
2821 return result<T, res_t>{std::in_place,
2822 std::move(*
this).res_()[index<0>]};
2859 template <
typename F>
2861 return transform_error(std::forward<F>(f));
2895 template <
typename F>
2897 return transform_error(std::forward<F>(f));
2931 template <
typename F>
2933 return std::move(*
this).transform_error(std::forward<F>(f));
2967 template <
typename F>
2969 return std::move(*
this).transform_error(std::forward<F>(f));
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};
2994 return result<reference, error_reference>{std::in_place, **
this};
2997 if constexpr (std::is_void_v<E>) {
2998 return result<reference, error_reference>{in_place_error};
3000 return result<reference, error_reference>{in_place_error, error()};
3022 [[nodiscard]]
constexpr result<const_reference, error_const_reference>
ref()
3024 if (res_().index() == 0) {
3025 if constexpr (std::is_void_v<T>) {
3026 return result<const_reference, error_const_reference>{std::in_place};
3028 return result<const_reference, error_const_reference>{std::in_place,
3032 if constexpr (std::is_void_v<E>) {
3033 return result<const_reference, error_const_reference>{in_place_error};
3035 return result<const_reference, error_const_reference>{in_place_error,
3058 [[nodiscard]]
constexpr result<const_reference, error_const_reference>
cref()
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};
3088 return option<T>{std::in_place, res_()[index<0>]};
3116 if (res_().index() == 0) {
3117 if constexpr (std::is_void_v<T>) {
3118 return option<T>{std::in_place};
3120 return option<T>{std::in_place, std::move(*
this).res_()[index<0>]};
3147 [[nodiscard]]
constexpr option<T>
ok_or_none()
const&
noexcept {
return or_none(); }
3169 [[nodiscard]]
constexpr option<T>
ok_or_none() && {
return std::move(*
this).or_none(); }
3192 if (res_().index() != 0) {
3193 if constexpr (std::is_void_v<E>) {
3194 return option<E>{std::in_place};
3196 return option<E>{std::in_place, res_()[index<1>]};
3224 if (res_().index() != 0) {
3225 if constexpr (std::is_void_v<E>) {
3226 return option<E>{std::in_place};
3228 return option<E>{std::in_place, std::move(*
this).res_()[index<1>]};
3256 template <
typename... Args>
3258 return res_().
template emplace<0>(std::forward<Args>(args)...);
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)...);
3308 template <
typename... Args>
3310 return res_().
template emplace<1>(std::forward<Args>(args)...);
3334 template <
typename U,
typename... Args>
3337 return res_().
template emplace<1>(ilist, std::forward<Args>(args)...);
3369 template <
typename V>
3377 return res_().visit(std::forward<V>(visitor));
3409 template <
typename V>
3417 return res_().visit(std::forward<V>(visitor));
3449 template <
typename V>
3457 return std::move(*
this).res_().visit(std::forward<V>(visitor));
3489 template <
typename V>
3497 return std::move(*
this).res_().visit(std::forward<V>(visitor));
3553 template <
typename V>
3561 return res_().visit_informed(std::forward<V>(visitor));
3617 template <
typename V>
3625 return res_().visit_informed(std::forward<V>(visitor));
3681 template <
typename V>
3689 return std::move(*
this).res_().visit_informed(std::forward<V>(visitor));
3745 template <
typename V>
3753 return std::move(*
this).res_().visit_informed(std::forward<V>(visitor));
3785 res_().swap(other.res_);
3814 template <size_t IDX,
typename T,
typename E>
3817 typename detail::traits<detail::select_t<IDX, T, E>>::
reference
3822 return get<IDX>(res.res_);
3850 template <size_t IDX,
typename T,
typename E>
3857 get(
const result<T, E>& res) {
3858 return get<IDX>(res.res_);
3886 template <size_t IDX,
typename T,
typename E>
3895 return get<IDX>(std::move(res.res_));
3923 template <size_t IDX,
typename T,
typename E>
3930 get(
const result<T, E>&& res) {
3931 return get<IDX>(std::move(res.res_));
3962 template <
typename U,
typename T,
typename E>
3973 return get<U>(res.res_);
4004 template <
typename U,
typename T,
typename E>
4014 get(
const result<T, E>& res) {
4015 return get<U>(res.res_);
4046 template <
typename U,
typename T,
typename E>
4058 return get<U>(std::move(res.res_));
4089 template <
typename U,
typename T,
typename E>
4099 get(
const result<T, E>&& res) {
4100 return get<U>(std::move(res.res_));
4117 template <
typename T,
typename E,
typename U,
typename V>
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();
4127 if (rhs.has_value()) {
4128 return *lhs == *rhs;
4134 if constexpr (std::is_void_v<E>) {
4135 return !rhs.has_value();
4137 if (rhs.has_value()) {
4140 return lhs.error() == rhs.error();
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;
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;
4209 template <
typename T,
typename E>
4210 constexpr void swap(result<T, E>& a, result<T, E>& b)
4237 template <
typename T,
typename... Args>
4239 return result<T,
never>{std::in_place, std::forward<Args>(args)...};
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)...};
4282 template <
typename E,
typename... Args>
4284 return result<
never, E>{in_place_error, std::forward<Args>(args)...};
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)...};
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 {};