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 an Android implementation of the std::expected
26 // proposal.
27 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0323r7.html
28 //
29 // Usage:
30 // using android::base::expected;
31 // using android::base::unexpected;
32 //
33 // expected<double,std::string> safe_divide(double i, double j) {
34 //   if (j == 0) return unexpected("divide by zero");
35 //   else return i / j;
36 // }
37 //
38 // void test() {
39 //   auto q = safe_divide(10, 0);
40 //   if (q) { printf("%f\n", q.value()); }
41 //   else { printf("%s\n", q.error().c_str()); }
42 // }
43 //
44 // When the proposal becomes part of the standard and is implemented by
45 // libcxx, this will be removed and android::base::expected will be
46 // type alias to std::expected.
47 //
48 
49 namespace android {
50 namespace base {
51 
52 // Synopsis
53 template<class T, class E>
54     class expected;
55 
56 template<class E>
57     class unexpected;
58 template<class E>
59   unexpected(E) -> unexpected<E>;
60 
61 template<class E>
62    class bad_expected_access;
63 
64 template<>
65    class bad_expected_access<void>;
66 
67 struct unexpect_t {
68    explicit unexpect_t() = default;
69 };
70 inline constexpr unexpect_t unexpect{};
71 
72 // macros for SFINAE
73 #define _ENABLE_IF(...) \
74   , std::enable_if_t<(__VA_ARGS__)>* = nullptr
75 
76 // Define NODISCARD_EXPECTED to prevent expected<T,E> from being
77 // ignored when used as a return value. This is off by default.
78 #ifdef NODISCARD_EXPECTED
79 #define _NODISCARD_ [[nodiscard]]
80 #else
81 #define _NODISCARD_
82 #endif
83 
84 // Class expected
85 template<class T, class E>
86 class _NODISCARD_ expected {
87  public:
88   using value_type = T;
89   using error_type = E;
90   using unexpected_type = unexpected<E>;
91 
92   template<class U>
93   using rebind = expected<U, error_type>;
94 
95   // constructors
96   constexpr expected() = default;
97   constexpr expected(const expected& rhs) = default;
98   constexpr expected(expected&& rhs) noexcept = default;
99 
100   template<class U, class G _ENABLE_IF(
101     std::is_constructible_v<T, const U&> &&
102     std::is_constructible_v<E, const G&> &&
103     !std::is_constructible_v<T, expected<U, G>&> &&
104     !std::is_constructible_v<T, expected<U, G>&&> &&
105     !std::is_constructible_v<T, const expected<U, G>&> &&
106     !std::is_constructible_v<T, const expected<U, G>&&> &&
107     !std::is_convertible_v<expected<U, G>&, T> &&
108     !std::is_convertible_v<expected<U, G>&&, T> &&
109     !std::is_convertible_v<const expected<U, G>&, T> &&
110     !std::is_convertible_v<const expected<U, G>&&, T> &&
111     !(!std::is_convertible_v<const U&, T> ||
112      !std::is_convertible_v<const G&, E>) /* non-explicit */
113   )>
114   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const expected<U,G> & rhs)115   constexpr expected(const expected<U, G>& rhs) {
116     if (rhs.has_value()) var_ = rhs.value();
117     else var_ = unexpected(rhs.error());
118   }
119 
120   template<class U, class G _ENABLE_IF(
121     std::is_constructible_v<T, const U&> &&
122     std::is_constructible_v<E, const G&> &&
123     !std::is_constructible_v<T, expected<U, G>&> &&
124     !std::is_constructible_v<T, expected<U, G>&&> &&
125     !std::is_constructible_v<T, const expected<U, G>&> &&
126     !std::is_constructible_v<T, const expected<U, G>&&> &&
127     !std::is_convertible_v<expected<U, G>&, T> &&
128     !std::is_convertible_v<expected<U, G>&&, T> &&
129     !std::is_convertible_v<const expected<U, G>&, T> &&
130     !std::is_convertible_v<const expected<U, G>&&, T> &&
131     (!std::is_convertible_v<const U&, T> ||
132      !std::is_convertible_v<const G&, E>) /* explicit */
133   )>
expected(const expected<U,G> & rhs)134   constexpr explicit expected(const expected<U, G>& rhs) {
135     if (rhs.has_value()) var_ = rhs.value();
136     else var_ = unexpected(rhs.error());
137   }
138 
139   template<class U, class G _ENABLE_IF(
140     std::is_constructible_v<T, const U&> &&
141     std::is_constructible_v<E, const G&> &&
142     !std::is_constructible_v<T, expected<U, G>&> &&
143     !std::is_constructible_v<T, expected<U, G>&&> &&
144     !std::is_constructible_v<T, const expected<U, G>&> &&
145     !std::is_constructible_v<T, const expected<U, G>&&> &&
146     !std::is_convertible_v<expected<U, G>&, T> &&
147     !std::is_convertible_v<expected<U, G>&&, T> &&
148     !std::is_convertible_v<const expected<U, G>&, T> &&
149     !std::is_convertible_v<const expected<U, G>&&, T> &&
150     !(!std::is_convertible_v<const U&, T> ||
151      !std::is_convertible_v<const G&, E>) /* non-explicit */
152   )>
153   // NOLINTNEXTLINE(google-explicit-constructor)
expected(expected<U,G> && rhs)154   constexpr expected(expected<U, G>&& rhs) {
155     if (rhs.has_value()) var_ = std::move(rhs.value());
156     else var_ = unexpected(std::move(rhs.error()));
157   }
158 
159   template<class U, class G _ENABLE_IF(
160     std::is_constructible_v<T, const U&> &&
161     std::is_constructible_v<E, const G&> &&
162     !std::is_constructible_v<T, expected<U, G>&> &&
163     !std::is_constructible_v<T, expected<U, G>&&> &&
164     !std::is_constructible_v<T, const expected<U, G>&> &&
165     !std::is_constructible_v<T, const expected<U, G>&&> &&
166     !std::is_convertible_v<expected<U, G>&, T> &&
167     !std::is_convertible_v<expected<U, G>&&, T> &&
168     !std::is_convertible_v<const expected<U, G>&, T> &&
169     !std::is_convertible_v<const expected<U, G>&&, T> &&
170     (!std::is_convertible_v<const U&, T> ||
171      !std::is_convertible_v<const G&, E>) /* explicit */
172   )>
expected(expected<U,G> && rhs)173   constexpr explicit expected(expected<U, G>&& rhs) {
174     if (rhs.has_value()) var_ = std::move(rhs.value());
175     else var_ = unexpected(std::move(rhs.error()));
176   }
177 
178   template <class U = T _ENABLE_IF(
179                 std::is_constructible_v<T, U&&> &&
180                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<U>>, std::in_place_t> &&
181                 !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
182                 !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
183                 std::is_convertible_v<U&&, T> /* non-explicit */
184                 )>
185   // NOLINTNEXTLINE(google-explicit-constructor,bugprone-forwarding-reference-overload)
expected(U && v)186   constexpr expected(U&& v) : var_(std::in_place_index<0>, std::forward<U>(v)) {}
187 
188   template <class U = T _ENABLE_IF(
189                 std::is_constructible_v<T, U&&> &&
190                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<U>>, std::in_place_t> &&
191                 !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
192                 !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
193                 !std::is_convertible_v<U&&, T> /* explicit */
194                 )>
195   // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
expected(U && v)196   constexpr explicit expected(U&& v) : var_(std::in_place_index<0>, T(std::forward<U>(v))) {}
197 
198   template<class G = E _ENABLE_IF(
199     std::is_constructible_v<E, const G&> &&
200     std::is_convertible_v<const G&, E> /* non-explicit */
201   )>
202   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const unexpected<G> & e)203   constexpr expected(const unexpected<G>& e)
204   : var_(std::in_place_index<1>, e.value()) {}
205 
206   template<class G = E _ENABLE_IF(
207     std::is_constructible_v<E, const G&> &&
208     !std::is_convertible_v<const G&, E> /* explicit */
209   )>
expected(const unexpected<G> & e)210   constexpr explicit expected(const unexpected<G>& e)
211   : var_(std::in_place_index<1>, E(e.value())) {}
212 
213   template<class G = E _ENABLE_IF(
214     std::is_constructible_v<E, G&&> &&
215     std::is_convertible_v<G&&, E> /* non-explicit */
216   )>
217   // NOLINTNEXTLINE(google-explicit-constructor)
expected(unexpected<G> && e)218   constexpr expected(unexpected<G>&& e)
219   : var_(std::in_place_index<1>, std::move(e.value())) {}
220 
221   template<class G = E _ENABLE_IF(
222     std::is_constructible_v<E, G&&> &&
223     !std::is_convertible_v<G&&, E> /* explicit */
224   )>
expected(unexpected<G> && e)225   constexpr explicit expected(unexpected<G>&& e)
226   : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
227 
228   template<class... Args _ENABLE_IF(
229     std::is_constructible_v<T, Args&&...>
230   )>
expected(std::in_place_t,Args &&...args)231   constexpr explicit expected(std::in_place_t, Args&&... args)
232   : var_(std::in_place_index<0>, std::forward<Args>(args)...) {}
233 
234   template<class U, class... Args _ENABLE_IF(
235     std::is_constructible_v<T, std::initializer_list<U>&, Args...>
236   )>
expected(std::in_place_t,std::initializer_list<U> il,Args &&...args)237   constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
238   : var_(std::in_place_index<0>, il, std::forward<Args>(args)...) {}
239 
240   template<class... Args _ENABLE_IF(
241     std::is_constructible_v<E, Args...>
242   )>
expected(unexpect_t,Args &&...args)243   constexpr explicit expected(unexpect_t, Args&&... args)
244   : var_(unexpected_type(std::forward<Args>(args)...)) {}
245 
246   template<class U, class... Args _ENABLE_IF(
247     std::is_constructible_v<E, std::initializer_list<U>&, Args...>
248   )>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)249   constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
250   : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
251 
252   // destructor
253   ~expected() = default;
254 
255   // assignment
256   // Note: SFNAIE doesn't work here because assignment operator should be
257   // non-template. We could workaround this by defining a templated parent class
258   // having the assignment operator. This incomplete implementation however
259   // doesn't allow us to copy assign expected<T,E> even when T is non-copy
260   // assignable. The copy assignment will fail by the underlying std::variant
261   // anyway though the error message won't be clear.
262   expected& operator=(const expected& rhs) = default;
263 
264   // Note for SFNAIE above applies to here as well
265   expected& operator=(expected&& rhs) noexcept(
266       std::is_nothrow_move_assignable_v<T>&& std::is_nothrow_move_assignable_v<E>) = default;
267 
268   template <class U = T _ENABLE_IF(
269                 !std::is_void_v<T> &&
270                 !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
271                 !std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::decay_t<U>>> &&
272                 std::is_constructible_v<T, U> && std::is_assignable_v<T&, U> &&
273                 std::is_nothrow_move_constructible_v<E>)>
274   expected& operator=(U&& rhs) {
275     var_ = T(std::forward<U>(rhs));
276     return *this;
277   }
278 
279   template<class G = E>
280   expected& operator=(const unexpected<G>& rhs) {
281     var_ = rhs;
282     return *this;
283   }
284 
285   template<class G = E _ENABLE_IF(
286     std::is_nothrow_move_constructible_v<G> &&
287     std::is_move_assignable_v<G>
288   )>
289   expected& operator=(unexpected<G>&& rhs) {
290     var_ = std::move(rhs);
291     return *this;
292   }
293 
294   // modifiers
295   template<class... Args _ENABLE_IF(
296     std::is_nothrow_constructible_v<T, Args...>
297   )>
emplace(Args &&...args)298   T& emplace(Args&&... args) {
299     expected(std::in_place, std::forward<Args>(args)...).swap(*this);
300     return value();
301   }
302 
303   template<class U, class... Args _ENABLE_IF(
304     std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>
305   )>
emplace(std::initializer_list<U> il,Args &&...args)306   T& emplace(std::initializer_list<U> il, Args&&... args) {
307     expected(std::in_place, il, std::forward<Args>(args)...).swap(*this);
308     return value();
309   }
310 
311   // swap
312   template<typename U = T, typename = std::enable_if_t<(
313     std::is_swappable_v<U> &&
314     std::is_swappable_v<E> &&
315     (std::is_move_constructible_v<U> ||
316      std::is_move_constructible_v<E>))>>
swap(expected & rhs)317   void swap(expected& rhs) noexcept(
318     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 explicit operator bool() const noexcept { return has_value(); }
has_value()334   constexpr bool has_value() const noexcept { return var_.index() == 0; }
ok()335   constexpr bool ok() const noexcept { return has_value(); }
336 
value()337   constexpr const T& value() const& { return std::get<T>(var_); }
value()338   constexpr T& value() & { return std::get<T>(var_); }
value()339   constexpr const T&& value() const&& { return std::move(std::get<T>(var_)); }
value()340   constexpr T&& value() && { return std::move(std::get<T>(var_)); }
341 
error()342   constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
error()343   constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
error()344   constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
error()345   constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
346 
347   template<class U _ENABLE_IF(
348     std::is_copy_constructible_v<T> &&
349     std::is_convertible_v<U, T>
350   )>
value_or(U && v)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   )>
value_or(U && v)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   // Specialized algorithms
382   template<class T1, class E1>
383   friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
384 
385  private:
386   std::variant<value_type, unexpected_type> var_;
387 };
388 
389 template<class T1, class E1, class T2, class E2>
390 constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
391   if (x.has_value() != y.has_value()) return false;
392   if (!x.has_value()) return x.error() == y.error();
393   return *x == *y;
394 }
395 
396 template<class T1, class E1, class T2, class E2>
397 constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y) {
398   return !(x == y);
399 }
400 
401 // Comparison with unexpected<E>
402 template<class T1, class E1, class E2>
403 constexpr bool operator==(const expected<T1, E1>& x, const unexpected<E2>& y) {
404   return !x.has_value() && (x.error() == y.value());
405 }
406 template<class T1, class E1, class E2>
407 constexpr bool operator==(const unexpected<E2>& x, const expected<T1, E1>& y) {
408   return !y.has_value() && (x.value() == y.error());
409 }
410 template<class T1, class E1, class E2>
411 constexpr bool operator!=(const expected<T1, E1>& x, const unexpected<E2>& y) {
412   return x.has_value() || (x.error() != y.value());
413 }
414 template<class T1, class E1, class E2>
415 constexpr bool operator!=(const unexpected<E2>& x, const expected<T1, E1>& y) {
416   return y.has_value() || (x.value() != y.error());
417 }
418 
419 template<class E>
420 class _NODISCARD_ expected<void, E> {
421  public:
422   using value_type = void;
423   using error_type = E;
424   using unexpected_type = unexpected<E>;
425 
426   // constructors
427   constexpr expected() = default;
428   constexpr expected(const expected& rhs) = default;
429   constexpr expected(expected&& rhs) noexcept = default;
430 
431   template<class U, class G _ENABLE_IF(
432     std::is_void_v<U> &&
433     std::is_convertible_v<const G&, E> /* non-explicit */
434   )>
435   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const expected<U,G> & rhs)436   constexpr expected(const expected<U, G>& rhs) {
437     if (!rhs.has_value()) var_ = unexpected(rhs.error());
438   }
439 
440   template<class U, class G _ENABLE_IF(
441     std::is_void_v<U> &&
442     !std::is_convertible_v<const G&, E> /* explicit */
443   )>
expected(const expected<U,G> & rhs)444   constexpr explicit expected(const expected<U, G>& rhs) {
445     if (!rhs.has_value()) var_ = unexpected(rhs.error());
446   }
447 
448   template<class U, class G _ENABLE_IF(
449     std::is_void_v<U> &&
450     std::is_convertible_v<const G&&, E> /* non-explicit */
451   )>
452   // NOLINTNEXTLINE(google-explicit-constructor)
expected(expected<U,G> && rhs)453   constexpr expected(expected<U, G>&& rhs) {
454     if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
455   }
456 
457   template<class U, class G _ENABLE_IF(
458     std::is_void_v<U> &&
459     !std::is_convertible_v<const G&&, E> /* explicit */
460   )>
expected(expected<U,G> && rhs)461   constexpr explicit expected(expected<U, G>&& rhs) {
462     if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
463   }
464 
465   template<class G = E _ENABLE_IF(
466     std::is_constructible_v<E, const G&> &&
467     std::is_convertible_v<const G&, E> /* non-explicit */
468   )>
469   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const unexpected<G> & e)470   constexpr expected(const unexpected<G>& e)
471   : var_(std::in_place_index<1>, e.value()) {}
472 
473   template<class G = E _ENABLE_IF(
474     std::is_constructible_v<E, const G&> &&
475     !std::is_convertible_v<const G&, E> /* explicit */
476   )>
expected(const unexpected<G> & e)477   constexpr explicit expected(const unexpected<G>& e)
478   : var_(std::in_place_index<1>, E(e.value())) {}
479 
480   template<class G = E _ENABLE_IF(
481     std::is_constructible_v<E, G&&> &&
482     std::is_convertible_v<G&&, E> /* non-explicit */
483   )>
484   // NOLINTNEXTLINE(google-explicit-constructor)
expected(unexpected<G> && e)485   constexpr expected(unexpected<G>&& e)
486   : var_(std::in_place_index<1>, std::move(e.value())) {}
487 
488   template<class G = E _ENABLE_IF(
489     std::is_constructible_v<E, G&&> &&
490     !std::is_convertible_v<G&&, E> /* explicit */
491   )>
expected(unexpected<G> && e)492   constexpr explicit expected(unexpected<G>&& e)
493   : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
494 
495   template<class... Args _ENABLE_IF(
496     sizeof...(Args) == 0
497   )>
expected(std::in_place_t,Args &&...)498   constexpr explicit expected(std::in_place_t, Args&&...) {}
499 
500   template<class... Args _ENABLE_IF(
501     std::is_constructible_v<E, Args...>
502   )>
expected(unexpect_t,Args &&...args)503   constexpr explicit expected(unexpect_t, Args&&... args)
504   : var_(unexpected_type(std::forward<Args>(args)...)) {}
505 
506   template<class U, class... Args _ENABLE_IF(
507     std::is_constructible_v<E, std::initializer_list<U>&, Args...>
508   )>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)509   constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
510   : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
511 
512   // destructor
513   ~expected() = default;
514 
515   // assignment
516   // Note: SFNAIE doesn't work here because assignment operator should be
517   // non-template. We could workaround this by defining a templated parent class
518   // having the assignment operator. This incomplete implementation however
519   // doesn't allow us to copy assign expected<T,E> even when T is non-copy
520   // assignable. The copy assignment will fail by the underlying std::variant
521   // anyway though the error message won't be clear.
522   expected& operator=(const expected& rhs) = default;
523 
524   // Note for SFNAIE above applies to here as well
525   expected& operator=(expected&& rhs) noexcept(std::is_nothrow_move_assignable_v<E>) = default;
526 
527   template<class G = E>
528   expected& operator=(const unexpected<G>& rhs) {
529     var_ = rhs;
530     return *this;
531   }
532 
533   template<class G = E _ENABLE_IF(
534     std::is_nothrow_move_constructible_v<G> &&
535     std::is_move_assignable_v<G>
536   )>
537   expected& operator=(unexpected<G>&& rhs) {
538     var_ = std::move(rhs);
539     return *this;
540   }
541 
542   // modifiers
emplace()543   void emplace() {
544     var_ = std::monostate();
545   }
546 
547   // swap
548   template<typename = std::enable_if_t<
549     std::is_swappable_v<E>>
550   >
swap(expected & rhs)551   void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<E>) {
552     var_.swap(rhs.var_);
553   }
554 
555   // observers
556   constexpr explicit operator bool() const noexcept { return has_value(); }
has_value()557   constexpr bool has_value() const noexcept { return var_.index() == 0; }
ok()558   constexpr bool ok() const noexcept { return has_value(); }
559 
value()560   constexpr void value() const& { if (!has_value()) std::get<0>(var_); }
561 
error()562   constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
error()563   constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
error()564   constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
error()565   constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
566 
567   // expected equality operators
568   template<class E1, class E2>
569   friend constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y);
570 
571   // Specialized algorithms
572   template<class T1, class E1>
573   friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
574 
575  private:
576   std::variant<std::monostate, unexpected_type> var_;
577 };
578 
579 template<class E1, class E2>
580 constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y) {
581   if (x.has_value() != y.has_value()) return false;
582   if (!x.has_value()) return x.error() == y.error();
583   return true;
584 }
585 
586 template<class T1, class E1, class E2>
587 constexpr bool operator==(const expected<T1, E1>& x, const expected<void, E2>& y) {
588   if (x.has_value() != y.has_value()) return false;
589   if (!x.has_value()) return x.error() == y.error();
590   return false;
591 }
592 
593 template<class E1, class T2, class E2>
594 constexpr bool operator==(const expected<void, E1>& x, const expected<T2, E2>& y) {
595   if (x.has_value() != y.has_value()) return false;
596   if (!x.has_value()) return x.error() == y.error();
597   return false;
598 }
599 
600 template<class E>
601 class unexpected {
602  public:
603   // constructors
604   constexpr unexpected(const unexpected&) = default;
605   constexpr unexpected(unexpected&&) noexcept(std::is_nothrow_move_constructible_v<E>) = default;
606 
607   template <class Err = E _ENABLE_IF(
608                 std::is_constructible_v<E, Err> &&
609                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
610                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
611   // NOLINTNEXTLINE(google-explicit-constructor,bugprone-forwarding-reference-overload)
unexpected(Err && e)612   constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
613 
614   template<class U, class... Args _ENABLE_IF(
615     std::is_constructible_v<E, std::initializer_list<U>&, Args...>
616   )>
unexpected(std::in_place_t,std::initializer_list<U> il,Args &&...args)617   constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
618   : val_(il, std::forward<Args>(args)...) {}
619 
620   template<class Err _ENABLE_IF(
621     std::is_constructible_v<E, Err> &&
622     !std::is_constructible_v<E, unexpected<Err>&> &&
623     !std::is_constructible_v<E, unexpected<Err>> &&
624     !std::is_constructible_v<E, const unexpected<Err>&> &&
625     !std::is_constructible_v<E, const unexpected<Err>> &&
626     !std::is_convertible_v<unexpected<Err>&, E> &&
627     !std::is_convertible_v<unexpected<Err>, E> &&
628     !std::is_convertible_v<const unexpected<Err>&, E> &&
629     !std::is_convertible_v<const unexpected<Err>, E> &&
630     std::is_convertible_v<Err, E> /* non-explicit */
631   )>
632   // NOLINTNEXTLINE(google-explicit-constructor)
unexpected(const unexpected<Err> & rhs)633   constexpr unexpected(const unexpected<Err>& rhs)
634   : val_(rhs.value()) {}
635 
636   template<class Err _ENABLE_IF(
637     std::is_constructible_v<E, Err> &&
638     !std::is_constructible_v<E, unexpected<Err>&> &&
639     !std::is_constructible_v<E, unexpected<Err>> &&
640     !std::is_constructible_v<E, const unexpected<Err>&> &&
641     !std::is_constructible_v<E, const unexpected<Err>> &&
642     !std::is_convertible_v<unexpected<Err>&, E> &&
643     !std::is_convertible_v<unexpected<Err>, E> &&
644     !std::is_convertible_v<const unexpected<Err>&, E> &&
645     !std::is_convertible_v<const unexpected<Err>, E> &&
646     !std::is_convertible_v<Err, E> /* explicit */
647   )>
unexpected(const unexpected<Err> & rhs)648   constexpr explicit unexpected(const unexpected<Err>& rhs)
649   : val_(E(rhs.value())) {}
650 
651   template<class Err _ENABLE_IF(
652     std::is_constructible_v<E, Err> &&
653     !std::is_constructible_v<E, unexpected<Err>&> &&
654     !std::is_constructible_v<E, unexpected<Err>> &&
655     !std::is_constructible_v<E, const unexpected<Err>&> &&
656     !std::is_constructible_v<E, const unexpected<Err>> &&
657     !std::is_convertible_v<unexpected<Err>&, E> &&
658     !std::is_convertible_v<unexpected<Err>, E> &&
659     !std::is_convertible_v<const unexpected<Err>&, E> &&
660     !std::is_convertible_v<const unexpected<Err>, E> &&
661     std::is_convertible_v<Err, E> /* non-explicit */
662   )>
663   // NOLINTNEXTLINE(google-explicit-constructor)
unexpected(unexpected<Err> && rhs)664   constexpr unexpected(unexpected<Err>&& rhs)
665   : val_(std::move(rhs.value())) {}
666 
667   template<class Err _ENABLE_IF(
668     std::is_constructible_v<E, Err> &&
669     !std::is_constructible_v<E, unexpected<Err>&> &&
670     !std::is_constructible_v<E, unexpected<Err>> &&
671     !std::is_constructible_v<E, const unexpected<Err>&> &&
672     !std::is_constructible_v<E, const unexpected<Err>> &&
673     !std::is_convertible_v<unexpected<Err>&, E> &&
674     !std::is_convertible_v<unexpected<Err>, E> &&
675     !std::is_convertible_v<const unexpected<Err>&, E> &&
676     !std::is_convertible_v<const unexpected<Err>, E> &&
677     !std::is_convertible_v<Err, E> /* explicit */
678   )>
unexpected(unexpected<Err> && rhs)679   constexpr explicit unexpected(unexpected<Err>&& rhs)
680   : val_(E(std::move(rhs.value()))) {}
681 
682   // assignment
683   constexpr unexpected& operator=(const unexpected&) = default;
684   constexpr unexpected& operator=(unexpected&&) noexcept(std::is_nothrow_move_assignable_v<E>) =
685       default;
686   template<class Err = E>
687   constexpr unexpected& operator=(const unexpected<Err>& rhs) {
688     val_ = rhs.value();
689     return *this;
690   }
691   template<class Err = E>
692   constexpr unexpected& operator=(unexpected<Err>&& rhs) {
693     val_ = std::forward<E>(rhs.value());
694     return *this;
695   }
696 
697   // observer
value()698   constexpr const E& value() const& noexcept { return val_; }
value()699   constexpr E& value() & noexcept { return val_; }
value()700   constexpr const E&& value() const&& noexcept { return std::move(val_); }
value()701   constexpr E&& value() && noexcept { return std::move(val_); }
702 
swap(unexpected & other)703   void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
704     std::swap(val_, other.val_);
705   }
706 
707   template<class E1, class E2>
708   friend constexpr bool
709   operator==(const unexpected<E1>& e1, const unexpected<E2>& e2);
710   template<class E1, class E2>
711   friend constexpr bool
712   operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2);
713 
714   template<class E1>
715   friend void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y)));
716 
717  private:
718   E val_;
719 };
720 
721 template<class E1, class E2>
722 constexpr bool
723 operator==(const unexpected<E1>& e1, const unexpected<E2>& e2) {
724   return e1.value() == e2.value();
725 }
726 
727 template<class E1, class E2>
728 constexpr bool
729 operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2) {
730   return e1.value() != e2.value();
731 }
732 
733 template<class E1>
swap(unexpected<E1> & x,unexpected<E1> & y)734 void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y))) {
735   x.swap(y);
736 }
737 
738 // TODO: bad_expected_access class
739 
740 #undef _ENABLE_IF
741 #undef _NODISCARD_
742 
743 }  // namespace base
744 }  // namespace android
745