@@ -55,7 +55,7 @@ unexpected(E) -> unexpected<E>;
5555template <class S , class E >
5656class [[nodiscard]] expected {
5757public:
58- constexpr expected () noexcept (std::is_void_v<S>) ;
58+ constexpr expected ();
5959 expected (const S& success);
6060 expected (S&& success);
6161 expected (const unexpected<E>& error);
@@ -70,6 +70,9 @@ class [[nodiscard]] expected {
7070 // / @brief Check whether *this contains an expected value
7171 bool has_value () const noexcept ;
7272
73+ // / @brief Check whether *this contains an expected value
74+ explicit operator bool () const noexcept ;
75+
7376 // / @brief Return reference to the value or throws bad_expected_access
7477 // / if it's not available
7578 // / @throws utils::bad_expected_access if *this contain an unexpected value
@@ -93,6 +96,30 @@ class [[nodiscard]] expected {
9396 std::variant<S, unexpected<E>> data_;
9497};
9598
99+ template <class E >
100+ class [[nodiscard]] expected<void , E> {
101+ public:
102+ constexpr expected () noexcept ;
103+ expected (const unexpected<E>& error);
104+ expected (unexpected<E>&& error);
105+
106+ template <class G , typename = std::enable_if_t <std::is_convertible_v<G, E>>>
107+ expected (const unexpected<G>& error);
108+
109+ template <class G , typename = std::enable_if_t <std::is_convertible_v<G, E>>>
110+ expected (unexpected<G>&& error);
111+
112+ bool has_value () const noexcept ;
113+ explicit operator bool () const noexcept ;
114+ void value () const ;
115+
116+ E& error ();
117+ const E& error () const ;
118+
119+ private:
120+ std::variant<std::monostate, unexpected<E>> data_;
121+ };
122+
96123template <class E >
97124unexpected<E>::unexpected(const E& error)
98125 : value_{error}
@@ -126,7 +153,7 @@ const E& unexpected<E>::error() const noexcept {
126153}
127154
128155template <class S , class E >
129- constexpr expected<S, E>::expected() noexcept (std::is_void_v<S>)
156+ constexpr expected<S, E>::expected()
130157 : data_(std::in_place_index<0 >)
131158{}
132159
@@ -167,6 +194,11 @@ bool expected<S, E>::has_value() const noexcept {
167194 return std::holds_alternative<S>(data_);
168195}
169196
197+ template <class S , class E >
198+ expected<S, E>::operator bool () const noexcept {
199+ return has_value ();
200+ }
201+
170202template <class S , class E >
171203S& expected<S, E>::value() & {
172204 S* result = std::get_if<S>(&data_);
@@ -208,6 +240,66 @@ const E& expected<S, E>::error() const {
208240 return result->error ();
209241}
210242
243+ template <class E >
244+ constexpr expected<void , E>::expected() noexcept : data_(std::in_place_index<0 >) {}
245+
246+ template <class E >
247+ expected<void , E>::expected(const unexpected<E>& error)
248+ : data_(error.error())
249+ {}
250+
251+ template <class E >
252+ expected<void , E>::expected(unexpected<E>&& error)
253+ : data_(std::forward<unexpected<E>>(error.error()))
254+ {}
255+
256+ template <class E >
257+ template <class G , typename >
258+ expected<void , E>::expected(const unexpected<G>& error)
259+ : data_(utils::unexpected<E>(std::forward<G>(error.error())))
260+ {}
261+
262+ template <class E >
263+ template <class G , typename >
264+ expected<void , E>::expected(unexpected<G>&& error)
265+ : data_(utils::unexpected<E>(std::forward<G>(error.error())))
266+ {}
267+
268+ template <class E >
269+ bool expected<void , E>::has_value() const noexcept {
270+ return data_.index () == 0 ;
271+ }
272+
273+ template <class E >
274+ expected<void , E>::operator bool () const noexcept {
275+ return has_value ();
276+ }
277+
278+ template <class E >
279+ void expected<void , E>::value() const {
280+ if (!has_value ()) {
281+ throw bad_expected_access (" Trying to get undefined value from utils::expected" );
282+ }
283+ }
284+
285+ template <class E >
286+ E& expected<void , E>::error() {
287+ auto * result = std::get_if<unexpected<E>>(&data_);
288+ if (result == nullptr ) {
289+ throw bad_expected_access (" Trying to get undefined error value from utils::expected" );
290+ }
291+ return result->error ();
292+ }
293+
294+ template <class E >
295+ const E& expected<void , E>::error() const {
296+ const auto * result = std::get_if<unexpected<E>>(&data_);
297+ if (result == nullptr ) {
298+ throw bad_expected_access (" Trying to get undefined error value from utils::expected" );
299+ }
300+ return result->error ();
301+ }
302+
211303// NOLINTEND(readability-identifier-naming)
212304
213305} // namespace utils
0 commit comments