di 0.1.0
Loading...
Searching...
No Matches
expected_void_value.h
Go to the documentation of this file.
1#pragma once
2
6#include "di/meta/compare.h"
8#include "di/meta/util.h"
9#include "di/meta/vocab.h"
10#include "di/util/forward.h"
12#include "di/util/move.h"
13#include "di/util/swap.h"
20
21namespace di::vocab {
22template<typename E>
23class [[nodiscard]] Expected<void, E> : public function::monad::MonadInterface<Expected<void, E>> {
24private:
25 using ErrorStorage = Optional<E>;
26
27public:
28 using Value = void;
29 using Error = E;
31
32 constexpr Expected() = default;
33
34 constexpr Expected(Expected const&)
36 = default;
37 constexpr Expected(Expected const&)
39 = delete;
40
41 constexpr Expected(Expected&&)
43 = default;
44
45 template<typename F>
47 concepts::detail::ExpectedCanConvertConstructor<void, E, void, F>)
49 : m_error(other.m_error) {}
50
51 template<typename F>
52 requires(concepts::ConstructibleFrom<E, F> && concepts::detail::ExpectedCanConvertConstructor<void, E, void, F>)
54 : m_error(util::move(other).m_error) {}
55
56 template<typename G>
59 : m_error(error.error()) {}
60
61 template<typename G>
64 : m_error(util::move(error).error()) {}
65
66 constexpr explicit Expected(types::InPlace) {}
67
68 template<typename... Args>
69 requires(concepts::ConstructibleFrom<E, Args...>)
70 constexpr explicit Expected(types::Unexpect, Args&&... args)
71 : m_error(types::in_place, util::forward<Args>(args)...) {}
72
73 template<typename U, typename... Args>
75 constexpr explicit Expected(types::Unexpect, std::initializer_list<U> list, Args&&... args)
76 : m_error(types::in_place, list, util::forward<Args>(args)...) {}
77
78 constexpr ~Expected() = default;
79
80 constexpr auto operator=(Expected const&) -> Expected&
82 = delete;
83 constexpr auto operator=(Expected const&) -> Expected&
85 = default;
86
87 constexpr auto operator=(Expected&&) -> Expected&
89 = default;
90
91 template<typename G>
93 constexpr auto operator=(Unexpected<G> const& error) -> Expected& {
94 m_error = error.error();
95 return *this;
96 }
97
98 template<typename G>
100 constexpr auto operator=(Unexpected<G>&& error) -> Expected& {
101 m_error = util::move(error).error();
102 return *this;
103 }
104
105 constexpr explicit operator bool() const { return has_value(); }
106 constexpr auto has_value() const -> bool { return !m_error.has_value(); }
107
108 constexpr void emplace() { m_error.reset(); }
109
110 constexpr void operator*() const { DI_ASSERT(has_value()); }
111
112 constexpr void value() const& { DI_ASSERT(has_value()); }
113
114 constexpr void value() && { DI_ASSERT(has_value()); }
115
116 constexpr auto error() & -> E& { return *m_error; }
117 constexpr auto error() const& -> E const& { return *m_error; }
118 constexpr auto error() && -> E&& { return *util::move(m_error); }
119 constexpr auto error() const&& -> E const&& { return *util::move(m_error); }
120
121 constexpr auto __try_did_fail() && -> Unexpected<E> {
122 return Unexpected<E> { in_place, util::move(*this).error() };
123 }
124 constexpr auto __try_did_succeed() && -> Expected { return Expected {}; }
125 constexpr void __try_move_out() && { return util::move(*this).value(); }
126
127private:
128 template<typename U, typename G>
129 friend class Expected;
130
131 constexpr friend void tag_invoke(types::Tag<util::swap>, Expected& a, Expected& b)
132 requires(concepts::Swappable<E>)
133 {
134 util::swap(a.m_value, b.m_value);
135 }
136
137 template<concepts::EqualityComparableWith<E> G>
138 constexpr friend auto operator==(Expected const& a, Expected<void, G> const& b) -> bool {
139 if (a.has_value() != b.has_value()) {
140 return false;
141 }
142 return a.has_value() || a.error() == b.error();
143 }
144
145 template<concepts::EqualityComparableWith<E> G>
146 constexpr friend auto operator==(Expected const& a, Unexpected<G> const& b) -> bool {
147 return !a && a.error() == b.error();
148 }
149
150 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
151 typename U = meta::UnwrapRefDecay<meta::InvokeResult<F>>>
153 constexpr friend auto tag_invoke(types::Tag<function::monad::fmap>, Self&& self, F&& function) -> Expected<U, E> {
154 if (!self) {
155 return Expected<U, E> { types::unexpect, util::forward<Self>(self).error() };
156 }
157 if constexpr (concepts::LanguageVoid<U>) {
158 function::invoke(util::forward<F>(function));
159 return {};
160 } else {
161 return function::invoke(util::forward<F>(function));
162 }
163 }
164
165 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F, typename R = meta::InvokeResult<F>>
167 constexpr friend auto tag_invoke(types::Tag<function::monad::bind>, Self&& self, F&& function) -> R {
168 if (!self) {
169 return R { types::unexpect, util::forward<Self>(self).error() };
170 }
171 return function::invoke(util::forward<F>(function));
172 }
173
174 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
175 typename R = meta::InvokeResult<F, meta::Like<Self, E>>>
177 constexpr friend auto tag_invoke(types::Tag<function::monad::fail>, Self&& self, F&& function) -> R {
178 if (self) {
179 return {};
180 }
181 return function::invoke(util::forward<F>(function), util::forward<Self>(self).error());
182 }
183
184 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
185 typename G = meta::UnwrapRefDecay<meta::InvokeResult<F, meta::Like<Self, E>>>>
186 constexpr friend auto tag_invoke(types::Tag<function::monad::fmap_right>, Self&& self, F&& function)
188 if (self) {
189 return {};
190 }
191 if constexpr (concepts::LanguageVoid<G>) {
192 function::invoke(util::forward<F>(function), util::forward<Self>(self).error());
193 return {};
194 } else {
196 util::forward<Self>(self).error()) };
197 }
198 }
199
200 Optional<E> m_error;
201};
202}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition monad_interface.h:15
constexpr Expected(types::InPlace)
Definition expected_void_value.h:66
constexpr friend auto tag_invoke(types::Tag< function::monad::fmap >, Self &&self, F &&function) -> Expected< U, E >
Definition expected_void_value.h:153
constexpr void operator*() const
Definition expected_void_value.h:110
constexpr friend auto operator==(Expected const &a, Expected< void, G > const &b) -> bool
Definition expected_void_value.h:138
friend class Expected
Definition expected_void_value.h:129
constexpr auto operator=(Expected const &) -> Expected &requires(!concepts::CopyConstructible< E >)=delete
E Error
Definition expected_void_value.h:29
constexpr auto error() const &-> E const &
Definition expected_void_value.h:117
constexpr friend void tag_invoke(types::Tag< util::swap >, Expected &a, Expected &b)
Definition expected_void_value.h:131
void Value
Definition expected_void_value.h:28
Unexpected< E > UnexpectedType
Definition expected_void_value.h:30
constexpr void value() const &
Definition expected_void_value.h:112
constexpr friend auto operator==(Expected const &a, Unexpected< G > const &b) -> bool
Definition expected_void_value.h:146
constexpr auto error() &-> E &
Definition expected_void_value.h:116
constexpr auto has_value() const -> bool
Definition expected_void_value.h:106
constexpr Expected(Expected &&)=default
constexpr Expected(types::Unexpect, std::initializer_list< U > list, Args &&... args)
Definition expected_void_value.h:75
constexpr Expected(Expected const &)=delete
constexpr auto operator=(Expected const &) -> Expected &requires(concepts::CopyConstructible< E >)=default
constexpr auto operator=(Expected &&) -> Expected &requires(concepts::MoveConstructible< E >)=default
constexpr friend auto tag_invoke(types::Tag< function::monad::fail >, Self &&self, F &&function) -> R
Definition expected_void_value.h:177
constexpr void emplace()
Definition expected_void_value.h:108
constexpr F const & other
Definition expected_void_value.h:52
constexpr Expected(Expected const &)=default
constexpr ~Expected()=default
constexpr void value() &&
Definition expected_void_value.h:114
constexpr Expected()=default
constexpr void __try_move_out() &&
Definition expected_void_value.h:125
constexpr Expected(types::Unexpect, Args &&... args)
Definition expected_void_value.h:70
constexpr auto __try_did_succeed() &&-> Expected
Definition expected_void_value.h:124
constexpr auto __try_did_fail() &&-> Unexpected< E >
Definition expected_void_value.h:121
constexpr friend auto tag_invoke(types::Tag< function::monad::fmap_right >, Self &&self, F &&function) -> Expected< void, G >
Definition expected_void_value.h:186
constexpr auto error() &&-> E &&
Definition expected_void_value.h:118
constexpr auto error() const &&-> E const &&
Definition expected_void_value.h:119
constexpr friend auto tag_invoke(types::Tag< function::monad::bind >, Self &&self, F &&function) -> R
Definition expected_void_value.h:167
Definition optional_forward_declaration.h:5
Definition unexpected.h:14
Definition operations.h:11
Definition operations.h:99
Definition operations.h:34
Definition vocab.h:30
Definition core.h:128
Definition operations.h:43
Definition swap.h:37
Definition as_bool.h:8
constexpr auto invoke
Definition invoke.h:100
meta::RemoveCVRef< T >::Error ExpectedError
Definition vocab.h:38
constexpr auto in_place
Definition in_place.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto unexpect
Definition unexpect.h:8
Definition vocab.h:96
constexpr struct di::util::SwapFunction swap
Definition lazy.h:165
constexpr auto in_place
Definition in_place.h:8
Definition in_place.h:4
Definition unexpect.h:4