xref: /aosp_15_r20/external/cronet/base/types/expected.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TYPES_EXPECTED_H_
6 #define BASE_TYPES_EXPECTED_H_
7 
8 #include <concepts>
9 #include <string_view>
10 #include <type_traits>
11 #include <utility>
12 
13 #include "base/check.h"
14 #include "base/strings/strcat.h"
15 #include "base/strings/to_string.h"
16 #include "base/types/expected_internal.h"  // IWYU pragma: export
17 #include "third_party/abseil-cpp/absl/utility/utility.h"
18 
19 // Class template `expected<T, E>` is a vocabulary type which contains an
20 // expected value of type `T`, or an error `E`. The class skews towards behaving
21 // like a `T`, because its intended use is when the expected type is contained.
22 // When something unexpected occurs, more typing is required. When all is good,
23 // code mostly looks as if a `T` were being handled.
24 //
25 // Class template `expected<T, E>` contains either:
26 // * A value of type `T`, the expected value type; or
27 // * A value of type `E`, an error type used when an unexpected outcome
28 // occurred.
29 //
30 // The interface can be queried as to whether the underlying value is the
31 // expected value (of type `T`) or an unexpected value (of type `E`). The
32 // interface and the rational are based on `std::optional`. We consider
33 // `expected<T, E>` as a supplement to `optional<T>`, expressing why an expected
34 // value isn’t contained in the object.
35 //
36 // Example Usage:
37 //
38 // Before:
39 //   bool ParseInt32(std::string_view input,
40 //                   int32_t* output,
41 //                   ParseIntError* error);
42 //   ...
43 //
44 //   int32_t output;
45 //   ParseIntError error;
46 //   if (ParseInt32("...". &output, &error)) {
47 //     // process `output`
48 //   } else {
49 //     // process `error`
50 //   }
51 //
52 // After:
53 //
54 //   base::expected<int32_t, ParseIntError> ParseInt32(std::string_view input);
55 //   ...
56 //
57 //   if (auto parsed = ParseInt32("..."); parsed.has_value()) {
58 //     // process `parsed.value()`
59 //   } else {
60 //     // process `parsed.error()`
61 //   }
62 //
63 // For even less boilerplate, see expected_macros.h.
64 //
65 // Note that there are various transformation member functions. To avoid having
66 // to puzzle through the standard-ese on their documentation, here's a quick
67 // reference table, assuming a source `expected<T, E> ex;` and types U and G
68 // convertible from T and E, respectively:
69 //
70 //                        Return type     Val when ex = t  Val when ex = e
71 //                        -----------     ---------------  ---------------
72 // ex.value_or(t2)        T               t                t2
73 // ex.and_then(f)         expected<U, E>  f(t)             unexpected(e)
74 // ex.transform(f)        expected<U, E>  expected(f(t))   unexpected(e)
75 // ex.or_else(f)          expected<T, G>  expected(t)      f(e)
76 // ex.transform_error(f)  expected<T, G>  expected(t)      unexpected(f(e))
77 //
78 // References:
79 // * https://wg21.link/P0323
80 // * https://eel.is/c++draft/expected
81 namespace base {
82 
83 // Note: base::unexpected and base::expected are C++17 compatible backports of
84 // C++23's std::unexpected and std::expected. They differ from the standard in
85 // the following ways:
86 //
87 // * Not all member functions can be used in a constexpr context. This is due to
88 //   limitations in both the C++17 language and the Abseil library used for the
89 //   implementation.
90 // * Since Chromium does not support exceptions, there is no bad_expected_access
91 //   exception and the program will just terminate when the exception would have
92 //   been thrown. Furthermore, all member functions are marked noexcept.
93 // * C++23 allows an implicit conversion from U to expected<T, E> if U is
94 //   implicitly convertible to T; the Chromium version only allows an implicit
95 //   conversion if U is implicitly convertible to T *and* U is *not* implicitly
96 //   convertible to E, to guard against bug-prone patterns such as:
97 //     // creates an expected value containing true, not an unexpected value
98 //     // containing 123L.
99 //     expected<bool, long> e = 123L;
100 // * Because of the above restriction, the Chromium version also introduces
101 //   `base::ok` as a complement to `base::unexpected` to simplify returning
102 //   success values when the implicit conversion above is disallowed.
103 // * Calling operator* or operator-> on an unexpected value results in program
104 //   termination, and not UB.
105 // * There is no operator bool due to bug-prone usage when the value type is
106 //   convertible to bool, see e.g. https://abseil.io/tips/141.
107 // * Moving out of an expected object will put it into a moved-from state.
108 //   Trying to use it before re-initializing it will result in program
109 //   termination.
110 // * The expected<void> specialization is done via a defaulted boolean template
111 //   parameter, due to the lack of requires clauses in C++17.
112 // * Since equality operators can not be defaulted in C++17, equality and
113 //   inequality operators are specified explicitly.
114 // * base::expected implements the monadic interface proposal
115 //   (https://wg21.link/P2505), which is currently only on track for C++26.
116 
117 // Class template used as a type hint for constructing a `base::expected`
118 // containing a value (i.e. success). Useful when implicit conversion
119 // construction of `base::expected` is disallowed, e.g. due to ambiguity.
120 // Example usage:
121 //
122 //   base::expected<std::string, std::string> RunOp() {
123 //     std::string error;
124 //     std::string result = RunOpImpl(..., &error);
125 //     if (!error.empty()) {
126 //       return base::unexpected(std::move(error));
127 //
128 //     // The C++23 std::expected proposal allows this to be simply written as
129 //     //   return result;
130 //     //
131 //     // However, the Chromium version disallows this if E implicitly converts
132 //     // to T, so without base::ok(), this would have to be written as:
133 //     //   return base::expected<std::string, std::string>(std::move(result));
134 //
135 //     return base::ok(std::move(result));
136 //   }
137 template <typename T>
138 class ok final {
139  public:
140   template <typename U = T>
requires(internal::IsOkValueConstruction<T,U>)141     requires(internal::IsOkValueConstruction<T, U>)
142   constexpr explicit ok(U&& val) noexcept : value_(std::forward<U>(val)) {}
143 
144   template <typename... Args>
ok(std::in_place_t,Args &&...args)145   constexpr explicit ok(std::in_place_t, Args&&... args) noexcept
146       : value_(std::forward<Args>(args)...) {}
147 
148   template <typename U, typename... Args>
ok(std::in_place_t,std::initializer_list<U> il,Args &&...args)149   constexpr explicit ok(std::in_place_t,
150                         std::initializer_list<U> il,
151                         Args&&... args) noexcept
152       : value_(il, std::forward<Args>(args)...) {}
153 
value()154   constexpr T& value() & noexcept { return value_; }
value()155   constexpr const T& value() const& noexcept { return value_; }
value()156   constexpr T&& value() && noexcept { return std::move(value()); }
value()157   constexpr const T&& value() const&& noexcept { return std::move(value()); }
158 
swap(ok & other)159   constexpr void swap(ok& other) noexcept {
160     using std::swap;
161     swap(value(), other.value());
162   }
163 
swap(ok & x,ok & y)164   friend constexpr void swap(ok& x, ok& y) noexcept { x.swap(y); }
165 
ToString()166   std::string ToString() const {
167     return StrCat({"ok(", base::ToString(value()), ")"});
168   }
169 
170  private:
171   T value_;
172 };
173 
174 template <typename T>
requires(std::is_void_v<T>)175   requires(std::is_void_v<T>)
176 class ok<T> final {
177  public:
178   constexpr explicit ok() noexcept = default;
179 
180   std::string ToString() const { return "ok()"; }
181 };
182 
183 template <typename T, typename U>
184 constexpr bool operator==(const ok<T>& lhs, const ok<U>& rhs) noexcept {
185   if constexpr (std::is_void_v<T> && std::is_void_v<U>) {
186     return true;
187   } else if constexpr (std::is_void_v<T> || std::is_void_v<U>) {
188     return false;
189   } else {
190     return lhs.value() == rhs.value();
191   }
192 }
193 
194 template <typename T, typename U>
195 constexpr bool operator!=(const ok<T>& lhs, const ok<U>& rhs) noexcept {
196   return !(lhs == rhs);
197 }
198 
199 template <typename T>
200 ok(T) -> ok<T>;
201 
202 ok()->ok<void>;
203 
204 // [expected.un.object], class template unexpected
205 // https://eel.is/c++draft/expected#un.object
206 template <typename E>
207 class unexpected final {
208  public:
209   // [expected.un.ctor] Constructors
210   template <typename Err = E>
requires(internal::IsUnexpectedValueConstruction<E,Err>)211     requires(internal::IsUnexpectedValueConstruction<E, Err>)
212   constexpr explicit unexpected(Err&& err) noexcept
213       : error_(std::forward<Err>(err)) {}
214 
215   template <typename... Args>
unexpected(std::in_place_t,Args &&...args)216   constexpr explicit unexpected(std::in_place_t, Args&&... args) noexcept
217       : error_(std::forward<Args>(args)...) {}
218 
219   template <typename U, typename... Args>
unexpected(std::in_place_t,std::initializer_list<U> il,Args &&...args)220   constexpr explicit unexpected(std::in_place_t,
221                                 std::initializer_list<U> il,
222                                 Args&&... args) noexcept
223       : error_(il, std::forward<Args>(args)...) {}
224 
225   // [expected.un.obs] Observers
error()226   constexpr E& error() & noexcept { return error_; }
error()227   constexpr const E& error() const& noexcept { return error_; }
error()228   constexpr E&& error() && noexcept { return std::move(error()); }
error()229   constexpr const E&& error() const&& noexcept { return std::move(error()); }
230 
231   // [expected.un.swap] Swap
swap(unexpected & other)232   constexpr void swap(unexpected& other) noexcept {
233     using std::swap;
234     swap(error(), other.error());
235   }
236 
swap(unexpected & x,unexpected & y)237   friend constexpr void swap(unexpected& x, unexpected& y) noexcept {
238     x.swap(y);
239   }
240 
241   // Deviation from the Standard: stringification support.
242   //
243   // If we move to `std::unexpected` someday, we would need to either forego
244   // nice formatted output or move to `std::format` or similar, which can have
245   // customized output for STL types.
ToString()246   std::string ToString() const noexcept {
247     return StrCat({"Unexpected(", base::ToString(error()), ")"});
248   }
249 
250  private:
251   E error_;
252 };
253 
254 // [expected.un.eq] Equality operator
255 template <typename E, typename G>
256 constexpr bool operator==(const unexpected<E>& lhs,
257                           const unexpected<G>& rhs) noexcept {
258   return lhs.error() == rhs.error();
259 }
260 
261 template <typename E, typename G>
262 constexpr bool operator!=(const unexpected<E>& lhs,
263                           const unexpected<G>& rhs) noexcept {
264   return !(lhs == rhs);
265 }
266 
267 template <typename E>
268 unexpected(E) -> unexpected<E>;
269 
270 // [expected.expected], class template expected
271 // https://eel.is/c++draft/expected#expected
272 template <typename T, typename E>
273 class [[nodiscard]] expected final {
274   // Note: A partial specialization for void value types follows below.
275   static_assert(!std::is_void_v<T>, "Error: T must not be void");
276 
277  public:
278   using value_type = T;
279   using error_type = E;
280   using unexpected_type = unexpected<E>;
281 
282   // Alias template to explicitly opt into the std::pointer_traits machinery.
283   // See e.g. https://en.cppreference.com/w/cpp/memory/pointer_traits#Notes
284   template <typename U>
285   using rebind = expected<U, E>;
286 
287   template <typename U, typename G>
288   friend class expected;
289 
290   // [expected.object.ctor], constructors
291   constexpr expected() noexcept = default;
292 
293   // Converting copy and move constructors. These constructors are explicit if
294   // either the value or error type is not implicitly convertible from `rhs`'s
295   // corresponding type.
296   template <typename U, typename G>
requires(internal::IsValidConversion<T,E,const U &,const G &>)297     requires(internal::IsValidConversion<T, E, const U&, const G&>)
298   explicit(!std::convertible_to<const U&, T> ||
299            !std::convertible_to<const G&, E>)
300       // NOLINTNEXTLINE(google-explicit-constructor)
301       constexpr expected(const expected<U, G>& rhs) noexcept
302       : impl_(rhs.impl_) {}
303 
304   template <typename U, typename G>
requires(internal::IsValidConversion<T,E,U,G>)305     requires(internal::IsValidConversion<T, E, U, G>)
306   explicit(!std::convertible_to<U, T> || !std::convertible_to<G, E>)
307       // NOLINTNEXTLINE(google-explicit-constructor)
308       constexpr expected(expected<U, G>&& rhs) noexcept
309       : impl_(std::move(rhs.impl_)) {}
310 
311   // Deviation from the Standard, which allows implicit conversions as long as U
312   // is implicitly convertible to T: Chromium additionally requires that U is
313   // not implicitly convertible to E.
314   template <typename U = T>
requires(internal::IsValidValueConstruction<T,E,U>)315     requires(internal::IsValidValueConstruction<T, E, U>)
316   explicit(!std::convertible_to<U, T> || std::convertible_to<U, E>)
317       // NOLINTNEXTLINE(google-explicit-constructor)
318       constexpr expected(U&& v) noexcept
319       : impl_(kValTag, std::forward<U>(v)) {}
320 
321   template <typename U>
requires(std::constructible_from<T,const U &>)322     requires(std::constructible_from<T, const U&>)
323   explicit(!std::convertible_to<const U&, T>)
324       // NOLINTNEXTLINE(google-explicit-constructor)
325       constexpr expected(const ok<U>& o) noexcept
326       : impl_(kValTag, o.value()) {}
327 
328   template <typename U>
requires(std::constructible_from<T,U>)329     requires(std::constructible_from<T, U>)
330   explicit(!std::convertible_to<U, T>)
331       // NOLINTNEXTLINE(google-explicit-constructor)
332       constexpr expected(ok<U>&& o) noexcept
333       : impl_(kValTag, std::move(o.value())) {}
334 
335   template <typename G>
requires(std::constructible_from<E,const G &>)336     requires(std::constructible_from<E, const G&>)
337   explicit(!std::convertible_to<const G&, E>)
338       // NOLINTNEXTLINE(google-explicit-constructor)
339       constexpr expected(const unexpected<G>& e) noexcept
340       : impl_(kErrTag, e.error()) {}
341 
342   template <typename G>
requires(std::constructible_from<E,G>)343     requires(std::constructible_from<E, G>)
344   explicit(!std::convertible_to<G, E>)
345       // NOLINTNEXTLINE(google-explicit-constructor)
346       constexpr expected(unexpected<G>&& e) noexcept
347       : impl_(kErrTag, std::move(e.error())) {}
348 
349   template <typename... Args>
expected(std::in_place_t,Args &&...args)350   constexpr explicit expected(std::in_place_t, Args&&... args) noexcept
351       : impl_(kValTag, std::forward<Args>(args)...) {}
352 
353   template <typename U, typename... Args>
expected(std::in_place_t,std::initializer_list<U> il,Args &&...args)354   constexpr explicit expected(std::in_place_t,
355                               std::initializer_list<U> il,
356                               Args&&... args) noexcept
357       : impl_(kValTag, il, std::forward<Args>(args)...) {}
358 
359   template <typename... Args>
expected(unexpect_t,Args &&...args)360   constexpr explicit expected(unexpect_t, Args&&... args) noexcept
361       : impl_(kErrTag, std::forward<Args>(args)...) {}
362 
363   template <typename U, typename... Args>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)364   constexpr explicit expected(unexpect_t,
365                               std::initializer_list<U> il,
366                               Args&&... args) noexcept
367       : impl_(kErrTag, il, std::forward<Args>(args)...) {}
368 
369   // [expected.object.assign], assignment
370   template <typename U = T>
requires(internal::IsValueAssignment<T,E,U>)371     requires(internal::IsValueAssignment<T, E, U>)
372   constexpr expected& operator=(U&& v) noexcept {
373     emplace(std::forward<U>(v));
374     return *this;
375   }
376 
377   template <typename U>
378   constexpr expected& operator=(const ok<U>& o) noexcept {
379     emplace(o.value());
380     return *this;
381   }
382 
383   template <typename U>
384   constexpr expected& operator=(ok<U>&& o) noexcept {
385     emplace(std::move(o.value()));
386     return *this;
387   }
388 
389   template <typename G>
390   constexpr expected& operator=(const unexpected<G>& e) noexcept {
391     impl_.emplace_error(e.error());
392     return *this;
393   }
394 
395   template <typename G>
396   constexpr expected& operator=(unexpected<G>&& e) noexcept {
397     impl_.emplace_error(std::move(e.error()));
398     return *this;
399   }
400 
401   template <typename... Args>
emplace(Args &&...args)402   constexpr T& emplace(Args&&... args) noexcept {
403     return impl_.emplace_value(std::forward<Args>(args)...);
404   }
405 
406   template <typename U, typename... Args>
emplace(std::initializer_list<U> il,Args &&...args)407   constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept {
408     return impl_.emplace_value(il, std::forward<Args>(args)...);
409   }
410 
411   // [expected.object.swap], swap
swap(expected & rhs)412   constexpr void swap(expected& rhs) noexcept { impl_.swap(rhs.impl_); }
swap(expected & x,expected & y)413   friend constexpr void swap(expected& x, expected& y) noexcept { x.swap(y); }
414 
415   // [expected.object.obs], observers
416   constexpr T* operator->() noexcept { return std::addressof(value()); }
417   constexpr const T* operator->() const noexcept {
418     return std::addressof(value());
419   }
420 
421   constexpr T& operator*() & noexcept { return value(); }
422   constexpr const T& operator*() const& noexcept { return value(); }
423   constexpr T&& operator*() && noexcept { return std::move(value()); }
424   constexpr const T&& operator*() const&& noexcept {
425     return std::move(value());
426   }
427 
428   // Note: Deviation from the Standard: No operator bool due to bug-prone
429   // patterns when the value type is convertible to bool, see e.g.
430   // https://abseil.io/tips/141.
has_value()431   constexpr bool has_value() const noexcept { return impl_.has_value(); }
432 
value()433   constexpr T& value() & noexcept { return impl_.value(); }
value()434   constexpr const T& value() const& noexcept { return impl_.value(); }
value()435   constexpr T&& value() && noexcept { return std::move(value()); }
value()436   constexpr const T&& value() const&& noexcept { return std::move(value()); }
437 
error()438   constexpr E& error() & noexcept { return impl_.error(); }
error()439   constexpr const E& error() const& noexcept { return impl_.error(); }
error()440   constexpr E&& error() && noexcept { return std::move(error()); }
error()441   constexpr const E&& error() const&& noexcept { return std::move(error()); }
442 
443   template <typename U>
value_or(U && v)444   constexpr T value_or(U&& v) const& noexcept {
445     static_assert(std::copy_constructible<T>,
446                   "expected<T, E>::value_or: T must be copy constructible");
447     static_assert(std::convertible_to<U&&, T>,
448                   "expected<T, E>::value_or: U must be convertible to T");
449     return has_value() ? value() : static_cast<T>(std::forward<U>(v));
450   }
451 
452   template <typename U>
value_or(U && v)453   constexpr T value_or(U&& v) && noexcept {
454     static_assert(std::move_constructible<T>,
455                   "expected<T, E>::value_or: T must be move constructible");
456     static_assert(std::convertible_to<U&&, T>,
457                   "expected<T, E>::value_or: U must be convertible to T");
458     return has_value() ? std::move(value())
459                        : static_cast<T>(std::forward<U>(v));
460   }
461 
462   template <typename G>
error_or(G && e)463   constexpr E error_or(G&& e) const& noexcept {
464     static_assert(std::copy_constructible<E>,
465                   "expected<T, E>::error_or: E must be copy constructible");
466     static_assert(std::convertible_to<G&&, E>,
467                   "expected<T, E>::error_or: G must be convertible to E");
468     return has_value() ? static_cast<E>(std::forward<G>(e)) : error();
469   }
470 
471   template <typename G>
error_or(G && e)472   constexpr E error_or(G&& e) && noexcept {
473     static_assert(std::move_constructible<E>,
474                   "expected<T, E>::error_or: E must be move constructible");
475     static_assert(std::convertible_to<G&&, E>,
476                   "expected<T, E>::error_or: G must be convertible to E");
477     return has_value() ? static_cast<E>(std::forward<G>(e))
478                        : std::move(error());
479   }
480 
481   // [expected.object.monadic], monadic operations
482   //
483   // This section implements the monadic interface consisting of `and_then`,
484   // `or_else`, `transform` and `transform_error`.
485 
486   // `and_then`: This methods accepts a callable `f` that is invoked with
487   // `value()` in case `has_value()` is true.
488   //
489   // `f`'s return type is required to be a (cvref-qualified) specialization of
490   // base::expected with a matching error_type, i.e. it needs to be of the form
491   // base::expected<U, E> cv ref for some U.
492   //
493   // If `has_value()` is false, this is effectively a no-op, and the function
494   // returns base::expected<U, E>(unexpect, std::forward<E>(error()));
495   //
496   // `and_then` is overloaded for all possible forms of const and ref
497   // qualifiers.
498   template <typename F>
requires(std::copy_constructible<E>)499     requires(std::copy_constructible<E>)
500   constexpr auto and_then(F&& f) & noexcept {
501     return internal::AndThen(*this, std::forward<F>(f));
502   }
503 
504   template <typename F>
requires(std::copy_constructible<E>)505     requires(std::copy_constructible<E>)
506   constexpr auto and_then(F&& f) const& noexcept {
507     return internal::AndThen(*this, std::forward<F>(f));
508   }
509 
510   template <typename F>
requires(std::move_constructible<E>)511     requires(std::move_constructible<E>)
512   constexpr auto and_then(F&& f) && noexcept {
513     return internal::AndThen(std::move(*this), std::forward<F>(f));
514   }
515 
516   template <typename F>
requires(std::move_constructible<E>)517     requires(std::move_constructible<E>)
518   constexpr auto and_then(F&& f) const&& noexcept {
519     return internal::AndThen(std::move(*this), std::forward<F>(f));
520   }
521 
522   // `or_else`: This methods accepts a callable `f` that is invoked with
523   // `error()` in case `has_value()` is false.
524   //
525   // `f`'s return type is required to be a (cvref-qualified) specialization of
526   // base::expected with a matching value_type, i.e. it needs to be of the form
527   // base::expected<T, G> cv ref for some G.
528   //
529   // If `has_value()` is true, this is effectively a no-op, and the function
530   // returns base::expected<T, G>(std::forward<T>(value()));
531   //
532   // `or_else` is overloaded for all possible forms of const and ref
533   // qualifiers.
534   template <typename F>
requires(std::copy_constructible<T>)535     requires(std::copy_constructible<T>)
536   constexpr auto or_else(F&& f) & noexcept {
537     return internal::OrElse(*this, std::forward<F>(f));
538   }
539 
540   template <typename F>
requires(std::copy_constructible<T>)541     requires(std::copy_constructible<T>)
542   constexpr auto or_else(F&& f) const& noexcept {
543     return internal::OrElse(*this, std::forward<F>(f));
544   }
545 
546   template <typename F>
requires(std::move_constructible<T>)547     requires(std::move_constructible<T>)
548   constexpr auto or_else(F&& f) && noexcept {
549     return internal::OrElse(std::move(*this), std::forward<F>(f));
550   }
551 
552   template <typename F>
requires(std::move_constructible<T>)553     requires(std::move_constructible<T>)
554   constexpr auto or_else(F&& f) const&& noexcept {
555     return internal::OrElse(std::move(*this), std::forward<F>(f));
556   }
557 
558   // `transform`: This methods accepts a callable `f` that is invoked with
559   // `value()` in case `has_value()` is true.
560   //
561   // `f`'s return type U needs to be a valid value_type for expected, i.e. any
562   // type for which `remove_cv_t` is either void, or a complete non-array object
563   // type that is not `absl::in_place_t`, `base::unexpect_t`, or a
564   // specialization of `base::ok` or `base::unexpected`.
565   //
566   // Returns an instance of base::expected<remove_cv_t<U>, E> that is
567   // constructed with f(value()) if there is a value, or unexpected(error())
568   // otherwise.
569   //
570   // `transform` is overloaded for all possible forms of const and ref
571   // qualifiers.
572   template <typename F>
requires(std::copy_constructible<E>)573     requires(std::copy_constructible<E>)
574   constexpr auto transform(F&& f) & noexcept {
575     return internal::Transform(*this, std::forward<F>(f));
576   }
577 
578   template <typename F>
requires(std::copy_constructible<E>)579     requires(std::copy_constructible<E>)
580   constexpr auto transform(F&& f) const& noexcept {
581     return internal::Transform(*this, std::forward<F>(f));
582   }
583 
584   template <typename F>
requires(std::move_constructible<E>)585     requires(std::move_constructible<E>)
586   constexpr auto transform(F&& f) && noexcept {
587     return internal::Transform(std::move(*this), std::forward<F>(f));
588   }
589 
590   template <typename F>
requires(std::move_constructible<E>)591     requires(std::move_constructible<E>)
592   constexpr auto transform(F&& f) const&& noexcept {
593     return internal::Transform(std::move(*this), std::forward<F>(f));
594   }
595 
596   // `transform_error`: This methods accepts a callable `f` that is invoked with
597   // `error()` in case `has_value()` is false.
598   //
599   // `f`'s return type G needs to be a valid error_type for expected, i.e. any
600   // type for which `remove_cv_t` is a complete non-array object type that is
601   // not `absl::in_place_t`, `base::unexpect_t`, or a specialization of
602   // `base::ok` or `base::unexpected`.
603   //
604   // Returns an instance of base::expected<T, remove_cv_t<G>> that is
605   // constructed with unexpected(f(error())) if there is no value, or value()
606   // otherwise.
607   //
608   // `transform_error` is overloaded for all possible forms of const and ref
609   // qualifiers.
610   template <typename F>
requires(std::copy_constructible<T>)611     requires(std::copy_constructible<T>)
612   constexpr auto transform_error(F&& f) & noexcept {
613     return internal::TransformError(*this, std::forward<F>(f));
614   }
615 
616   template <typename F>
requires(std::copy_constructible<T>)617     requires(std::copy_constructible<T>)
618   constexpr auto transform_error(F&& f) const& noexcept {
619     return internal::TransformError(*this, std::forward<F>(f));
620   }
621 
622   template <typename F>
requires(std::move_constructible<T>)623     requires(std::move_constructible<T>)
624   constexpr auto transform_error(F&& f) && noexcept {
625     return internal::TransformError(std::move(*this), std::forward<F>(f));
626   }
627 
628   template <typename F>
requires(std::move_constructible<T>)629     requires(std::move_constructible<T>)
630   constexpr auto transform_error(F&& f) const&& noexcept {
631     return internal::TransformError(std::move(*this), std::forward<F>(f));
632   }
633 
634   // Deviation from the Standard: stringification support.
635   //
636   // If we move to `std::expected` someday, we would need to either forego nice
637   // formatted output or move to `std::format` or similar, which can have
638   // customized output for STL types.
ToString()639   std::string ToString() const {
640     return has_value() ? StrCat({"Expected(", base::ToString(value()), ")"})
641                        : StrCat({"Unexpected(", base::ToString(error()), ")"});
642   }
643 
644  private:
645   using Impl = internal::ExpectedImpl<T, E>;
646   static constexpr auto kValTag = Impl::kValTag;
647   static constexpr auto kErrTag = Impl::kErrTag;
648 
649   Impl impl_;
650 };
651 
652 // [expected.void], partial specialization of expected for void types
653 template <typename T, typename E>
requires(std::is_void_v<T>)654   requires(std::is_void_v<T>)
655 class [[nodiscard]] expected<T, E> final {
656   // Note: A partial specialization for non-void value types can be found above.
657   static_assert(std::is_void_v<T>, "Error: T must be void");
658 
659  public:
660   using value_type = T;
661   using error_type = E;
662   using unexpected_type = unexpected<E>;
663 
664   // Alias template to explicitly opt into the std::pointer_traits machinery.
665   // See e.g. https://en.cppreference.com/w/cpp/memory/pointer_traits#Notes
666   template <typename U>
667   using rebind = expected<U, E>;
668 
669   template <typename U, typename G>
670   friend class expected;
671 
672   // [expected.void.ctor], constructors
673   constexpr expected() noexcept = default;
674 
675   // Converting copy and move constructors. These constructors are explicit if
676   // the error type is not implicitly convertible from `rhs`'s error type.
677   template <typename U, typename G>
678     requires(internal::IsValidVoidConversion<E, U, const G&>)
679   explicit(!std::convertible_to<const G&, E>)
680       // NOLINTNEXTLINE(google-explicit-constructor)
681       constexpr expected(const expected<U, G>& rhs) noexcept
682       : impl_(rhs.impl_) {}
683 
684   template <typename U, typename G>
685     requires(internal::IsValidVoidConversion<E, U, G>)
686   explicit(!std::convertible_to<G, E>)
687       // NOLINTNEXTLINE(google-explicit-constructor)
688       constexpr expected(expected<U, G>&& rhs) noexcept
689       : impl_(std::move(rhs.impl_)) {}
690 
691   // NOLINTNEXTLINE(google-explicit-constructor)
692   constexpr /* implicit */ expected(base::ok<T>) noexcept {}
693 
694   template <typename G>
695     requires(std::constructible_from<E, const G&>)
696   explicit(!std::convertible_to<const G&, E>)
697       // NOLINTNEXTLINE(google-explicit-constructor)
698       constexpr expected(const unexpected<G>& e) noexcept
699       : impl_(kErrTag, e.error()) {}
700 
701   template <typename G>
702     requires(std::constructible_from<E, G>)
703   explicit(!std::convertible_to<G, E>)
704       // NOLINTNEXTLINE(google-explicit-constructor)
705       constexpr expected(unexpected<G>&& e) noexcept
706       : impl_(kErrTag, std::move(e.error())) {}
707 
708   constexpr explicit expected(std::in_place_t) noexcept {}
709 
710   template <typename... Args>
711   constexpr explicit expected(unexpect_t, Args&&... args) noexcept
712       : impl_(kErrTag, std::forward<Args>(args)...) {}
713 
714   template <typename U, typename... Args>
715   constexpr explicit expected(unexpect_t,
716                               std::initializer_list<U> il,
717                               Args&&... args) noexcept
718       : impl_(kErrTag, il, std::forward<Args>(args)...) {}
719 
720   // [expected.void.assign], assignment
721   template <typename G>
722   constexpr expected& operator=(const unexpected<G>& e) noexcept {
723     impl_.emplace_error(e.error());
724     return *this;
725   }
726 
727   template <typename G>
728   constexpr expected& operator=(unexpected<G>&& e) noexcept {
729     impl_.emplace_error(std::move(e.error()));
730     return *this;
731   }
732 
733   constexpr void emplace() noexcept { impl_.emplace_value(); }
734 
735   // [expected.void.swap], swap
736   constexpr void swap(expected& rhs) noexcept { impl_.swap(rhs.impl_); }
737   friend constexpr void swap(expected& x, expected& y) noexcept { x.swap(y); }
738 
739   // [expected.void.obs], observers
740   // Note: Deviation from the Standard: No operator bool due to consistency with
741   // non-void expected types.
742   constexpr bool has_value() const noexcept { return impl_.has_value(); }
743 
744   constexpr void operator*() const { CHECK(has_value()); }
745   constexpr void value() const { CHECK(has_value()); }
746 
747   constexpr E& error() & { return impl_.error(); }
748   constexpr const E& error() const& { return impl_.error(); }
749   constexpr E&& error() && { return std::move(error()); }
750   constexpr const E&& error() const&& { return std::move(error()); }
751 
752   template <typename G>
753   constexpr E error_or(G&& e) const& noexcept {
754     static_assert(std::copy_constructible<E>,
755                   "expected<T, E>::error_or: E must be copy constructible");
756     static_assert(std::convertible_to<G&&, E>,
757                   "expected<T, E>::error_or: G must be convertible to E");
758     return has_value() ? static_cast<E>(std::forward<G>(e)) : error();
759   }
760 
761   template <typename G>
762   constexpr E error_or(G&& e) && noexcept {
763     static_assert(std::move_constructible<E>,
764                   "expected<T, E>::error_or: E must be move constructible");
765     static_assert(std::convertible_to<G&&, E>,
766                   "expected<T, E>::error_or: G must be convertible to E");
767     return has_value() ? static_cast<E>(std::forward<G>(e))
768                        : std::move(error());
769   }
770 
771   // [expected.void.monadic], monadic operations
772   //
773   // This section implements the monadic interface consisting of `and_then`,
774   // `or_else`, `transform` and `transform_error`. In contrast to the non void
775   // specialization it is mandated that the callables for `and_then` and
776   // `transform`don't take any arguments.
777 
778   // `and_then`: This methods accepts a callable `f` that is invoked with
779   // no arguments in case `has_value()` is true.
780   //
781   // `f`'s return type is required to be a (cvref-qualified) specialization of
782   // base::expected with a matching error_type, i.e. it needs to be of the form
783   // base::expected<U, E> cv ref for some U.
784   //
785   // If `has_value()` is false, this is effectively a no-op, and the function
786   // returns base::expected<U, E>(unexpect, std::forward<E>(error()));
787   //
788   // `and_then` is overloaded for all possible forms of const and ref
789   // qualifiers.
790   template <typename F>
791     requires(std::copy_constructible<E>)
792   constexpr auto and_then(F&& f) & noexcept {
793     return internal::AndThen(*this, std::forward<F>(f));
794   }
795 
796   template <typename F>
797     requires(std::copy_constructible<E>)
798   constexpr auto and_then(F&& f) const& noexcept {
799     return internal::AndThen(*this, std::forward<F>(f));
800   }
801 
802   template <typename F>
803     requires(std::move_constructible<E>)
804   constexpr auto and_then(F&& f) && noexcept {
805     return internal::AndThen(std::move(*this), std::forward<F>(f));
806   }
807 
808   template <typename F>
809     requires(std::move_constructible<E>)
810   constexpr auto and_then(F&& f) const&& noexcept {
811     return internal::AndThen(std::move(*this), std::forward<F>(f));
812   }
813 
814   // `or_else`: This methods accepts a callable `f` that is invoked with
815   // `error()` in case `has_value()` is false.
816   //
817   // `f`'s return type is required to be a (cvref-qualified) specialization of
818   // base::expected with a matching value_type, i.e. it needs to be cv void.
819   //
820   // If `has_value()` is true, this is effectively a no-op, and the function
821   // returns base::expected<cv void, G>().
822   //
823   // `or_else` is overloaded for all possible forms of const and ref
824   // qualifiers.
825   template <typename F>
826   constexpr auto or_else(F&& f) & noexcept {
827     return internal::OrElse(*this, std::forward<F>(f));
828   }
829 
830   template <typename F>
831   constexpr auto or_else(F&& f) const& noexcept {
832     return internal::OrElse(*this, std::forward<F>(f));
833   }
834 
835   template <typename F>
836   constexpr auto or_else(F&& f) && noexcept {
837     return internal::OrElse(std::move(*this), std::forward<F>(f));
838   }
839 
840   template <typename F>
841   constexpr auto or_else(F&& f) const&& noexcept {
842     return internal::OrElse(std::move(*this), std::forward<F>(f));
843   }
844 
845   // `transform`: This methods accepts a callable `f` that is invoked with no
846   // arguments in case `has_value()` is true.
847   //
848   // `f`'s return type U needs to be a valid value_type for expected, i.e. any
849   // type for which `remove_cv_t` is either void, or a complete non-array object
850   // type that is not `absl::in_place_t`, `base::unexpect_t`, or a
851   // specialization of `base::ok` or `base::unexpected`.
852   //
853   // Returns an instance of base::expected<remove_cv_t<U>, E> that is
854   // constructed with f() if has_value() is true, or unexpected(error())
855   // otherwise.
856   //
857   // `transform` is overloaded for all possible forms of const and ref
858   // qualifiers.
859   template <typename F>
860     requires(std::copy_constructible<E>)
861   constexpr auto transform(F&& f) & noexcept {
862     return internal::Transform(*this, std::forward<F>(f));
863   }
864 
865   template <typename F>
866     requires(std::copy_constructible<E>)
867   constexpr auto transform(F&& f) const& noexcept {
868     return internal::Transform(*this, std::forward<F>(f));
869   }
870 
871   template <typename F>
872     requires(std::move_constructible<E>)
873   constexpr auto transform(F&& f) && noexcept {
874     return internal::Transform(std::move(*this), std::forward<F>(f));
875   }
876 
877   template <typename F>
878     requires(std::move_constructible<E>)
879   constexpr auto transform(F&& f) const&& noexcept {
880     return internal::Transform(std::move(*this), std::forward<F>(f));
881   }
882 
883   // `transform_error`: This methods accepts a callable `f` that is invoked with
884   // `error()` in case `has_value()` is false.
885   //
886   // `f`'s return type G needs to be a valid error_type for expected, i.e. any
887   // type for which `remove_cv_t` is a complete non-array object type that is
888   // not `absl::in_place_t`, `base::unexpect_t`, or a specialization of
889   // `base::ok` or `base::unexpected`.
890   //
891   // Returns an instance of base::expected<cv void, remove_cv_t<G>> that is
892   // constructed with unexpected(f(error())) if there is no value, or default
893   // constructed otherwise.
894   //
895   // `transform_error` is overloaded for all possible forms of const and ref
896   // qualifiers.
897   template <typename F>
898   constexpr auto transform_error(F&& f) & noexcept {
899     return internal::TransformError(*this, std::forward<F>(f));
900   }
901 
902   template <typename F>
903   constexpr auto transform_error(F&& f) const& noexcept {
904     return internal::TransformError(*this, std::forward<F>(f));
905   }
906 
907   template <typename F>
908   constexpr auto transform_error(F&& f) && noexcept {
909     return internal::TransformError(std::move(*this), std::forward<F>(f));
910   }
911 
912   template <typename F>
913   constexpr auto transform_error(F&& f) const&& noexcept {
914     return internal::TransformError(std::move(*this), std::forward<F>(f));
915   }
916 
917   // Deviation from the Standard: stringification support.
918   //
919   // If we move to `std::expected` someday, we would need to either forego nice
920   // formatted output or move to `std::format` or similar, which can have
921   // customized output for STL types.
922   std::string ToString() const {
923     return has_value() ? "Expected()"
924                        : StrCat({"Unexpected(", base::ToString(error()), ")"});
925   }
926 
927  private:
928   // Note: Since we can't store void types we use absl::monostate instead.
929   using Impl = internal::ExpectedImpl<absl::monostate, E>;
930   static constexpr auto kErrTag = Impl::kErrTag;
931 
932   Impl impl_;
933 };
934 
935 // [expected.object.eq], equality operators
936 // [expected.void.eq], equality operators
937 template <typename T, typename E, typename U, typename G>
938 constexpr bool operator==(const expected<T, E>& x,
939                           const expected<U, G>& y) noexcept {
940   if (x.has_value() != y.has_value()) {
941     return false;
942   }
943 
944   if (x.has_value()) {
945     // Values for expected void types always compare equal.
946     if constexpr (std::is_void_v<T> && std::is_void_v<U>) {
947       return true;
948     } else {
949       return x.value() == y.value();
950     }
951   }
952 
953   return x.error() == y.error();
954 }
955 
956 template <typename T, typename E, typename U>
957   requires(!std::is_void_v<T>)
958 constexpr bool operator==(const expected<T, E>& x, const U& v) noexcept {
959   return x.has_value() && x.value() == v;
960 }
961 
962 template <typename T, typename E, typename U>
963 constexpr bool operator==(const expected<T, E>& x, const ok<U>& o) noexcept {
964   if constexpr (std::is_void_v<T> && std::is_void_v<U>) {
965     return x.has_value();
966   } else if constexpr (std::is_void_v<T> || std::is_void_v<U>) {
967     return false;
968   } else {
969     return x.has_value() && x.value() == o.value();
970   }
971 }
972 
973 template <typename T, typename E, typename G>
974 constexpr bool operator==(const expected<T, E>& x,
975                           const unexpected<G>& e) noexcept {
976   return !x.has_value() && x.error() == e.error();
977 }
978 
979 }  // namespace base
980 
981 #endif  // BASE_TYPES_EXPECTED_H_
982