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