1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <algorithm>
20 #include <initializer_list>
21 #include <type_traits>
22 #include <utility>
23 #include <variant>
24 
25 // android::base::expected is a partial implementation of C++23's std::expected
26 // for Android.
27 //
28 // Usage:
29 // using android::base::expected;
30 // using android::base::unexpected;
31 //
32 // expected<double,std::string> safe_divide(double i, double j) {
33 //   if (j == 0) return unexpected("divide by zero");
34 //   else return i / j;
35 // }
36 //
37 // void test() {
38 //   auto q = safe_divide(10, 0);
39 //   if (q.ok()) { printf("%f\n", q.value()); }
40 //   else { printf("%s\n", q.error().c_str()); }
41 // }
42 //
43 // Once the Android platform has moved to C++23, this will be removed and
44 // android::base::expected will be type aliased to std::expected.
45 //
46 
47 namespace android {
48 namespace base {
49 
50 // Synopsis
51 template <class T, class E>
52 class expected;
53 
54 template <class E>
55 class unexpected;
56 template <class E>
57 unexpected(E) -> unexpected<E>;
58 
59 template <class E>
60 class bad_expected_access;
61 
62 template <>
63 class bad_expected_access<void>;
64 
65 struct unexpect_t {
66    explicit unexpect_t() = default;
67 };
68 inline constexpr unexpect_t unexpect{};
69 
70 // macros for SFINAE
71 #define _ENABLE_IF(...) \
72   , std::enable_if_t<(__VA_ARGS__)>* = nullptr
73 
74 // Define NODISCARD_EXPECTED to prevent expected<T,E> from being
75 // ignored when used as a return value. This is off by default.
76 #ifdef NODISCARD_EXPECTED
77 #define _NODISCARD_ [[nodiscard]]
78 #else
79 #define _NODISCARD_
80 #endif
81 
82 #define _EXPLICIT(cond)                                                     \
83   _Pragma("clang diagnostic push")                                          \
84   _Pragma("clang diagnostic ignored \"-Wc++20-extensions\"") explicit(cond) \
85   _Pragma("clang diagnostic pop")
86 
87 #define _COMMA ,
88 
89 namespace expected_internal {
90 
91 template <class T>
92 struct remove_cvref {
93   using type = std::remove_cv_t<std::remove_reference_t<T>>;
94 };
95 
96 template <class T>
97 using remove_cvref_t = typename remove_cvref<T>::type;
98 
99 // Can T be constructed from W (or W converted to T)? W can be lvalue or rvalue,
100 // const or not.
101 template <class T, class W>
102 inline constexpr bool converts_from_any_cvref =
103     std::disjunction_v<std::is_constructible<T, W&>, std::is_convertible<W&, T>,
104                        std::is_constructible<T, W>, std::is_convertible<W, T>,
105                        std::is_constructible<T, const W&>, std::is_convertible<const W&, T>,
106                        std::is_constructible<T, const W>, std::is_convertible<const W, T>>;
107 
108 template <class T>
109 struct is_expected : std::false_type {};
110 
111 template <class T, class E>
112 struct is_expected<expected<T, E>> : std::true_type {};
113 
114 template <class T>
115 inline constexpr bool is_expected_v = is_expected<T>::value;
116 
117 template <class T>
118 struct is_unexpected : std::false_type {};
119 
120 template <class E>
121 struct is_unexpected<unexpected<E>> : std::true_type {};
122 
123 template <class T>
124 inline constexpr bool is_unexpected_v = is_unexpected<T>::value;
125 
126 // Constraints on constructing an expected<T, ...> from an expected<U, G>
127 // related to T and U. UF is either "const U&" or "U".
128 template <class T, class U, class G, class UF>
129 inline constexpr bool convert_value_constraints =
130     std::is_constructible_v<T, UF> &&
131     (std::is_same_v<std::remove_cv_t<T>, bool> || !converts_from_any_cvref<T, expected<U, G>>);
132 
133 // Constraints on constructing an expected<..., E> from an expected<U, G>
134 // related to E, G, and expected<U, G>. GF is either "const G&" or "G".
135 template <class E, class U, class G, class GF>
136 inline constexpr bool convert_error_constraints =
137     std::is_constructible_v<E, GF> &&
138     !std::is_constructible_v<unexpected<E>, expected<U, G>&> &&
139     !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
140     !std::is_constructible_v<unexpected<E>, const expected<U, G>&> &&
141     !std::is_constructible_v<unexpected<E>, const expected<U, G>>;
142 
143 // If an exception is thrown in expected::operator=, while changing the expected
144 // object between a value and an error, the expected object is supposed to
145 // retain its original value, which is only possible if certain constructors
146 // are noexcept. This implementation doesn't try to be exception-safe, but
147 // enforce these constraints anyway because std::expected also will enforce
148 // them, and we intend to switch to it eventually.
149 template <class T, class E, class Self, class Value>
150 inline constexpr bool eh_assign_constraints =
151     std::is_nothrow_constructible_v<Self, Value> ||
152     std::is_nothrow_move_constructible_v<T> ||
153     std::is_nothrow_move_constructible_v<E>;
154 
155 // Implement expected<..., E>::expected([const] unexpected<G> [&/&&]).
156 #define _CONSTRUCT_EXPECTED_FROM_UNEXPECTED(GF, ParamType, forward_func)     \
157   template <class G _ENABLE_IF(std::is_constructible_v<E, GF>)>              \
158   constexpr _EXPLICIT((!std::is_convertible_v<GF, E>))                       \
159       expected(ParamType e) noexcept(std::is_nothrow_constructible_v<E, GF>) \
160       : var_(std::in_place_index<1>, forward_func(e.error())) {}
161 
162 // Implement expected<..., E>::operator=([const] unexpected<G> [&/&&]).
163 #define _ASSIGN_UNEXPECTED_TO_EXPECTED(GF, ParamType, forward_func, extra_constraints)          \
164   template <class G _ENABLE_IF(std::is_constructible_v<E, GF> &&                                \
165                                std::is_assignable_v<E&, GF>) &&                                 \
166                                extra_constraints>                                               \
167   constexpr expected& operator=(ParamType e) noexcept(std::is_nothrow_constructible_v<E, GF> && \
168                                                       std::is_nothrow_assignable_v<E&, GF>) {   \
169     if (has_value()) {                                                                          \
170       var_.template emplace<1>(forward_func(e.error()));                                        \
171     } else {                                                                                    \
172       error() = forward_func(e.error());                                                        \
173     }                                                                                           \
174     return *this;                                                                               \
175   }
176 
177 }  // namespace expected_internal
178 
179 // Class expected
180 template <class T, class E>
181 class _NODISCARD_ expected {
182   static_assert(std::is_object_v<T> && !std::is_array_v<T> &&
183                     !std::is_same_v<std::remove_cv_t<T>, std::in_place_t> &&
184                     !std::is_same_v<std::remove_cv_t<T>, unexpect_t> &&
185                     !expected_internal::is_unexpected_v<std::remove_cv_t<T>>,
186                 "expected value type cannot be a reference, a function, an array, in_place_t, "
187                 "unexpect_t, or unexpected");
188 
189  public:
190   using value_type = T;
191   using error_type = E;
192   using unexpected_type = unexpected<E>;
193 
194   template <class U>
195   using rebind = expected<U, error_type>;
196 
197   // Delegate simple operations to the underlying std::variant. std::variant
198   // doesn't set noexcept well, at least for copy ctor/assign, so set it
199   // explicitly. Technically the copy/move assignment operators should also be
200   // deleted if neither T nor E satisfies is_nothrow_move_constructible_v, but
201   // that would require making these operator= methods into template functions.
202   constexpr expected() = default;
203   constexpr expected(const expected& rhs) noexcept(
204       std::is_nothrow_copy_constructible_v<T> && std::is_nothrow_copy_constructible_v<E>) = default;
205   constexpr expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<T> &&
206                                               std::is_nothrow_move_constructible_v<E>) = default;
207   constexpr expected& operator=(const expected& rhs) noexcept(
208       std::is_nothrow_copy_constructible_v<T> && std::is_nothrow_copy_assignable_v<T> &&
209       std::is_nothrow_copy_constructible_v<E> && std::is_nothrow_copy_assignable_v<E>) = default;
210   constexpr expected& operator=(expected&& rhs) noexcept(
211       std::is_nothrow_move_constructible_v<T> && std::is_nothrow_move_assignable_v<T> &&
212       std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>) = default;
213 
214   // Construct this expected<T, E> from a different expected<U, G> type.
215 #define _CONVERTING_CTOR(UF, GF, ParamType, forward_func)                                      \
216   template <class U,                                                                           \
217             class G _ENABLE_IF(expected_internal::convert_value_constraints<T, U, G, UF> &&    \
218                                expected_internal::convert_error_constraints<E, U, G, GF>)>     \
219   constexpr _EXPLICIT((!std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>))        \
220       expected(ParamType rhs) noexcept(std::is_nothrow_constructible_v<T, UF> &&               \
221                                        std::is_nothrow_constructible_v<E, GF>)                 \
222       : var_(rhs.has_value() ? variant_type(std::in_place_index<0>, forward_func(rhs.value())) \
223                              : variant_type(std::in_place_index<1>, forward_func(rhs.error()))) {}
224 
225   // NOLINTNEXTLINE(google-explicit-constructor)
226   _CONVERTING_CTOR(const U&, const G&, const expected<U _COMMA G>&, )
227   // NOLINTNEXTLINE(google-explicit-constructor)
228   _CONVERTING_CTOR(U, G, expected<U _COMMA G>&&, std::move)
229 
230 #undef _CONVERTING_CTOR
231 
232   // Construct from (converted) success value, using a forwarding reference.
233   template <class U = T _ENABLE_IF(
234                 !std::is_same_v<expected_internal::remove_cvref_t<U>, std::in_place_t> &&
235                 !std::is_same_v<expected_internal::remove_cvref_t<U>, expected> &&
236                 !expected_internal::is_unexpected_v<expected_internal::remove_cvref_t<U>> &&
237                 std::is_constructible_v<T, U> &&
238                 (!std::is_same_v<std::remove_cv_t<T>, bool> ||
239                  !expected_internal::is_expected_v<expected_internal::remove_cvref_t<U>>))>
240   constexpr _EXPLICIT((!std::is_convertible_v<U, T>))
241       // NOLINTNEXTLINE(google-explicit-constructor)
242       expected(U&& v) noexcept(std::is_nothrow_constructible_v<T, U>)
243       : var_(std::in_place_index<0>, std::forward<U>(v)) {}
244 
245   // NOLINTNEXTLINE(google-explicit-constructor)
246   _CONSTRUCT_EXPECTED_FROM_UNEXPECTED(const G&, const unexpected<G>&, )
247   // NOLINTNEXTLINE(google-explicit-constructor)
248   _CONSTRUCT_EXPECTED_FROM_UNEXPECTED(G, unexpected<G>&&, std::move)
249 
250   // in_place_t construction
251   template <class... Args _ENABLE_IF(std::is_constructible_v<T, Args...>)>
252   constexpr explicit expected(std::in_place_t, Args&&... args)
253       noexcept(std::is_nothrow_constructible_v<T, Args...>)
254       : var_(std::in_place_index<0>, std::forward<Args>(args)...) {}
255 
256   // in_place_t with initializer_list construction
257   template <class U, class... Args _ENABLE_IF(
258       std::is_constructible_v<T, std::initializer_list<U>&, Args...>)>
259   constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
260       noexcept(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
261       : var_(std::in_place_index<0>, il, std::forward<Args>(args)...) {}
262 
263   // unexpect_t construction
264   template <class... Args _ENABLE_IF(std::is_constructible_v<E, Args...>)>
265   constexpr explicit expected(unexpect_t, Args&&... args)
266       noexcept(std::is_nothrow_constructible_v<E, Args...>)
267       : var_(std::in_place_index<1>, unexpected_type(std::forward<Args>(args)...)) {}
268 
269   // unexpect_t with initializer_list construction
270   template <class U, class... Args _ENABLE_IF(
271       std::is_constructible_v<E, std::initializer_list<U>&, Args...>)>
272   constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
273       noexcept(std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
274       : var_(std::in_place_index<1>, unexpected_type(il, std::forward<Args>(args)...)) {}
275 
276   // Assignment from (converted) success value, using a forwarding reference.
277   template <class U = T _ENABLE_IF(
278                 !std::is_same_v<expected, expected_internal::remove_cvref_t<U>> &&
279                 !expected_internal::is_unexpected_v<expected_internal::remove_cvref_t<U>> &&
280                 std::is_constructible_v<T, U> && std::is_assignable_v<T&, U> &&
281                 expected_internal::eh_assign_constraints<T, E, T, U>)>
282   constexpr expected& operator=(U&& v) noexcept(std::is_nothrow_constructible_v<T, U> &&
283                                                 std::is_nothrow_assignable_v<T&, U>) {
284     if (has_value()) {
285       value() = std::forward<U>(v);
286     } else {
287       var_.template emplace<0>(std::forward<U>(v));
288     }
289     return *this;
290   }
291 
292   _ASSIGN_UNEXPECTED_TO_EXPECTED(const G&, const unexpected<G>&, ,
293                                  (expected_internal::eh_assign_constraints<T, E, E, const G&>))
294   _ASSIGN_UNEXPECTED_TO_EXPECTED(G, unexpected<G>&&, std::move,
295                                  (expected_internal::eh_assign_constraints<T, E, E, G>))
296 
297   // modifiers
298   template <class... Args _ENABLE_IF(std::is_nothrow_constructible_v<T, Args...>)>
299   constexpr T& emplace(Args&&... args) noexcept {
300     var_.template emplace<0>(std::forward<Args>(args)...);
301     return value();
302   }
303 
304   template <class U, class... Args _ENABLE_IF(
305                          std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)>
306   constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept {
307     var_.template emplace<0>(il, std::forward<Args>(args)...);
308     return value();
309   }
310 
311   // Swap. This function takes a template argument so that _ENABLE_IF works.
312   template <class U = T _ENABLE_IF(
313                 std::is_same_v<U, T> &&
314                     std::is_swappable_v<T> && std::is_swappable_v<E> &&
315                     std::is_move_constructible_v<T> && std::is_move_constructible_v<E> &&
316                 (std::is_nothrow_move_constructible_v<T> ||
317                  std::is_nothrow_move_constructible_v<E>))>
318   constexpr void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<T> &&
319                                               std::is_nothrow_swappable_v<T> &&
320                                               std::is_nothrow_move_constructible_v<E> &&
321                                               std::is_nothrow_swappable_v<E>) {
322     var_.swap(rhs.var_);
323   }
324 
325   // observers
326   constexpr const T* operator->() const { return std::addressof(value()); }
327   constexpr T* operator->() { return std::addressof(value()); }
328   constexpr const T& operator*() const& { return value(); }
329   constexpr T& operator*() & { return value(); }
330   constexpr const T&& operator*() const&& { return std::move(std::get<T>(var_)); }
331   constexpr T&& operator*() && { return std::move(std::get<T>(var_)); }
332 
333   constexpr bool has_value() const noexcept { return var_.index() == 0; }
334   constexpr bool ok() const noexcept { return has_value(); }
335   constexpr explicit operator bool() const noexcept { return has_value(); }
336 
337   constexpr const T& value() const& { return std::get<T>(var_); }
338   constexpr T& value() & { return std::get<T>(var_); }
339   constexpr const T&& value() const&& { return std::move(std::get<T>(var_)); }
340   constexpr T&& value() && { return std::move(std::get<T>(var_)); }
341 
342   constexpr const E& error() const& { return std::get<unexpected_type>(var_).error(); }
343   constexpr E& error() & { return std::get<unexpected_type>(var_).error(); }
344   constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).error(); }
345   constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).error(); }
346 
347   template<class U _ENABLE_IF(
348     std::is_copy_constructible_v<T> &&
349     std::is_convertible_v<U, T>
350   )>
351   constexpr T value_or(U&& v) const& {
352     if (has_value()) return value();
353     else return static_cast<T>(std::forward<U>(v));
354   }
355 
356   template<class U _ENABLE_IF(
357     std::is_move_constructible_v<T> &&
358     std::is_convertible_v<U, T>
359   )>
360   constexpr T value_or(U&& v) && {
361     if (has_value()) return std::move(value());
362     else return static_cast<T>(std::forward<U>(v));
363   }
364 
365   // expected equality operators
366   template<class T1, class E1, class T2, class E2>
367   friend constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y);
368   template<class T1, class E1, class T2, class E2>
369   friend constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y);
370 
371   // Comparison with unexpected<E>
372   template<class T1, class E1, class E2>
373   friend constexpr bool operator==(const expected<T1, E1>&, const unexpected<E2>&);
374   template<class T1, class E1, class E2>
375   friend constexpr bool operator==(const unexpected<E2>&, const expected<T1, E1>&);
376   template<class T1, class E1, class E2>
377   friend constexpr bool operator!=(const expected<T1, E1>&, const unexpected<E2>&);
378   template<class T1, class E1, class E2>
379   friend constexpr bool operator!=(const unexpected<E2>&, const expected<T1, E1>&);
380 
381  private:
382   using variant_type = std::variant<value_type, unexpected_type>;
383   variant_type var_;
384 };
385 
386 template<class T1, class E1, class T2, class E2>
387 constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
388   if (x.has_value() != y.has_value()) return false;
389   if (!x.has_value()) return x.error() == y.error();
390   return *x == *y;
391 }
392 
393 template<class T1, class E1, class T2, class E2>
394 constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y) {
395   return !(x == y);
396 }
397 
398 // Comparison with unexpected<E>
399 template<class T1, class E1, class E2>
400 constexpr bool operator==(const expected<T1, E1>& x, const unexpected<E2>& y) {
401   return !x.has_value() && (x.error() == y.error());
402 }
403 template<class T1, class E1, class E2>
404 constexpr bool operator==(const unexpected<E2>& x, const expected<T1, E1>& y) {
405   return !y.has_value() && (x.error() == y.error());
406 }
407 template<class T1, class E1, class E2>
408 constexpr bool operator!=(const expected<T1, E1>& x, const unexpected<E2>& y) {
409   return x.has_value() || (x.error() != y.error());
410 }
411 template<class T1, class E1, class E2>
412 constexpr bool operator!=(const unexpected<E2>& x, const expected<T1, E1>& y) {
413   return y.has_value() || (x.error() != y.error());
414 }
415 
416 template<class E>
417 class _NODISCARD_ expected<void, E> {
418  public:
419   using value_type = void;
420   using error_type = E;
421   using unexpected_type = unexpected<E>;
422 
423   template <class U>
424   using rebind = expected<U, error_type>;
425 
426   // Delegate simple operations to the underlying std::variant.
427   constexpr expected() = default;
428   constexpr expected(const expected& rhs) noexcept(std::is_nothrow_copy_constructible_v<E>) =
429       default;
430   constexpr expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<E>) = default;
431   constexpr expected& operator=(const expected& rhs) noexcept(
432       std::is_nothrow_copy_constructible_v<E> && std::is_nothrow_copy_assignable_v<E>) = default;
433   constexpr expected& operator=(expected&& rhs) noexcept(
434       std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>) = default;
435 
436   // Construct this expected<void, E> from a different expected<U, G> type.
437 #define _CONVERTING_CTOR(GF, ParamType, forward_func)                                 \
438   template <class U, class G _ENABLE_IF(std::is_void_v<U> &&                          \
439         expected_internal::convert_error_constraints<E, U, G, GF>)>                   \
440   constexpr _EXPLICIT((!std::is_convertible_v<GF, E>))                                \
441       expected(ParamType rhs) noexcept(std::is_nothrow_constructible_v<E, GF>)        \
442       : var_(rhs.has_value() ? variant_type(std::in_place_index<0>, std::monostate()) \
443                              : variant_type(std::in_place_index<1>, forward_func(rhs.error()))) {}
444 
445   // NOLINTNEXTLINE(google-explicit-constructor)
446   _CONVERTING_CTOR(const G&, const expected<U _COMMA G>&, )
447   // NOLINTNEXTLINE(google-explicit-constructor)
448   _CONVERTING_CTOR(G, expected<U _COMMA G>&&, std::move)
449 
450 #undef _CONVERTING_CTOR
451 
452   // NOLINTNEXTLINE(google-explicit-constructor)
453   _CONSTRUCT_EXPECTED_FROM_UNEXPECTED(const G&, const unexpected<G>&, )
454   // NOLINTNEXTLINE(google-explicit-constructor)
455   _CONSTRUCT_EXPECTED_FROM_UNEXPECTED(G, unexpected<G>&&, std::move)
456 
457   // in_place_t construction
458   constexpr explicit expected(std::in_place_t) noexcept {}
459 
460   // unexpect_t construction
461   template <class... Args _ENABLE_IF(std::is_constructible_v<E, Args...>)>
462   constexpr explicit expected(unexpect_t, Args&&... args)
463       noexcept(std::is_nothrow_constructible_v<E, Args...>)
464       : var_(std::in_place_index<1>, unexpected_type(std::forward<Args>(args)...)) {}
465 
466   // unexpect_t with initializer_list construction
467   template <class U, class... Args _ENABLE_IF(
468                          std::is_constructible_v<E, std::initializer_list<U>&, Args...>)>
469   constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
470       noexcept(std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
471       : var_(std::in_place_index<1>, unexpected_type(il, std::forward<Args>(args)...)) {}
472 
473   _ASSIGN_UNEXPECTED_TO_EXPECTED(const G&, const unexpected<G>&, , true)
474   _ASSIGN_UNEXPECTED_TO_EXPECTED(G, unexpected<G>&&, std::move, true)
475 
476   // modifiers
477   constexpr void emplace() noexcept { var_.template emplace<0>(std::monostate()); }
478 
479   // Swap. This function takes a template argument so that _ENABLE_IF works.
480   template <class G = E _ENABLE_IF(std::is_same_v<G, E> &&
481                                    std::is_swappable_v<E> && std::is_move_constructible_v<E>)>
482   constexpr void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<E> &&
483                                               std::is_nothrow_swappable_v<E>) {
484     var_.swap(rhs.var_);
485   }
486 
487   // observers
488   constexpr bool has_value() const noexcept { return var_.index() == 0; }
489   constexpr bool ok() const noexcept { return has_value(); }
490   constexpr explicit operator bool() const noexcept { return has_value(); }
491 
492   constexpr void value() const& { if (!has_value()) std::get<0>(var_); }
493 
494   constexpr const E& error() const& { return std::get<1>(var_).error(); }
495   constexpr E& error() & { return std::get<1>(var_).error(); }
496   constexpr const E&& error() const&& { return std::move(std::get<1>(var_)).error(); }
497   constexpr E&& error() && { return std::move(std::get<1>(var_)).error(); }
498 
499   // expected equality operators
500   template<class E1, class E2>
501   friend constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y);
502 
503  private:
504   using variant_type = std::variant<std::monostate, unexpected_type>;
505   variant_type var_;
506 };
507 
508 template<class E1, class E2>
509 constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y) {
510   if (x.has_value() != y.has_value()) return false;
511   if (!x.has_value()) return x.error() == y.error();
512   return true;
513 }
514 
515 template<class T1, class E1, class E2>
516 constexpr bool operator==(const expected<T1, E1>& x, const expected<void, E2>& y) {
517   if (x.has_value() != y.has_value()) return false;
518   if (!x.has_value()) return x.error() == y.error();
519   return false;
520 }
521 
522 template<class E1, class T2, class E2>
523 constexpr bool operator==(const expected<void, E1>& x, const expected<T2, E2>& y) {
524   if (x.has_value() != y.has_value()) return false;
525   if (!x.has_value()) return x.error() == y.error();
526   return false;
527 }
528 
529 template <class T, class E, typename = decltype(
530     std::declval<expected<T, E>&>().swap(std::declval<expected<T, E>&>()))>
531 constexpr void swap(expected<T, E>& x, expected<T, E>& y) noexcept(noexcept(x.swap(y))) {
532   x.swap(y);
533 }
534 
535 template<class E>
536 class unexpected {
537   static_assert(std::is_object_v<E> && !std::is_array_v<E> && !std::is_const_v<E> &&
538                     !std::is_volatile_v<E> && !expected_internal::is_unexpected_v<E>,
539                 "unexpected error type cannot be a reference, a function, an array, cv-qualified, "
540                 "or unexpected");
541 
542  public:
543   // constructors
544   constexpr unexpected(const unexpected&) = default;
545   constexpr unexpected(unexpected&&) = default;
546 
547   template <class Err = E _ENABLE_IF(
548                 !std::is_same_v<expected_internal::remove_cvref_t<Err>, unexpected> &&
549                 !std::is_same_v<expected_internal::remove_cvref_t<Err>, std::in_place_t> &&
550                 std::is_constructible_v<E, Err>)>
551   constexpr explicit unexpected(Err&& e) noexcept(std::is_nothrow_constructible_v<E, Err>)
552       : val_(std::forward<Err>(e)) {}
553 
554   template <class... Args _ENABLE_IF(std::is_constructible_v<E, Args...>)>
555   constexpr explicit unexpected(std::in_place_t, Args&&... args)
556       noexcept(std::is_nothrow_constructible_v<E, Args...>)
557       : val_(std::forward<Args>(args)...) {}
558 
559   template <class U, class... Args _ENABLE_IF(
560                          std::is_constructible_v<E, std::initializer_list<U>&, Args...>)>
561   constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
562       noexcept(std::is_nothrow_constructible_v<E, std::initializer_list<U>&, Args...>)
563       : val_(il, std::forward<Args>(args)...) {}
564 
565   constexpr unexpected& operator=(const unexpected&) = default;
566   constexpr unexpected& operator=(unexpected&&) = default;
567 
568   // observer
569   constexpr const E& error() const& noexcept { return val_; }
570   constexpr E& error() & noexcept { return val_; }
571   constexpr const E&& error() const&& noexcept { return std::move(val_); }
572   constexpr E&& error() && noexcept { return std::move(val_); }
573 
574   // Swap. This function takes a template argument so that _ENABLE_IF works.
575   template <typename G = E _ENABLE_IF(std::is_same_v<G, E> && std::is_swappable_v<E>)>
576   void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
577     // Make std::swap visible to provide swap for STL and builtin types, but use
578     // an unqualified swap to invoke argument-dependent lookup to find the swap
579     // functions for user-declared types.
580     using std::swap;
581     swap(val_, other.val_);
582   }
583 
584   template<class E1, class E2>
585   friend constexpr bool
586   operator==(const unexpected<E1>& e1, const unexpected<E2>& e2);
587   template<class E1, class E2>
588   friend constexpr bool
589   operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2);
590 
591  private:
592   E val_;
593 };
594 
595 template<class E1, class E2>
596 constexpr bool
597 operator==(const unexpected<E1>& e1, const unexpected<E2>& e2) {
598   return e1.error() == e2.error();
599 }
600 
601 template<class E1, class E2>
602 constexpr bool
603 operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2) {
604   return e1.error() != e2.error();
605 }
606 
607 template <class E1 _ENABLE_IF(std::is_swappable_v<E1>)>
608 void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y))) {
609   x.swap(y);
610 }
611 
612 // TODO: bad_expected_access class
613 
614 #undef _ENABLE_IF
615 #undef _NODISCARD_
616 #undef _EXPLICIT
617 #undef _COMMA
618 #undef _CONSTRUCT_EXPECTED_FROM_UNEXPECTED
619 #undef _ASSIGN_UNEXPECTED_TO_EXPECTED
620 
621 }  // namespace base
622 }  // namespace android
623