• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
has_value()333   constexpr bool has_value() const noexcept { return var_.index() == 0; }
ok()334   constexpr bool ok() const noexcept { return has_value(); }
335 
value()336   constexpr const T& value() const& { return std::get<T>(var_); }
value()337   constexpr T& value() & { return std::get<T>(var_); }
value()338   constexpr const T&& value() const&& { return std::move(std::get<T>(var_)); }
value()339   constexpr T&& value() && { return std::move(std::get<T>(var_)); }
340 
error()341   constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
error()342   constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
error()343   constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
error()344   constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
345 
346   template<class U _ENABLE_IF(
347     std::is_copy_constructible_v<T> &&
348     std::is_convertible_v<U, T>
349   )>
value_or(U && v)350   constexpr T value_or(U&& v) const& {
351     if (has_value()) return value();
352     else return static_cast<T>(std::forward<U>(v));
353   }
354 
355   template<class U _ENABLE_IF(
356     std::is_move_constructible_v<T> &&
357     std::is_convertible_v<U, T>
358   )>
value_or(U && v)359   constexpr T value_or(U&& v) && {
360     if (has_value()) return std::move(value());
361     else return static_cast<T>(std::forward<U>(v));
362   }
363 
364   // expected equality operators
365   template<class T1, class E1, class T2, class E2>
366   friend constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y);
367   template<class T1, class E1, class T2, class E2>
368   friend constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y);
369 
370   // Comparison with unexpected<E>
371   template<class T1, class E1, class E2>
372   friend constexpr bool operator==(const expected<T1, E1>&, const unexpected<E2>&);
373   template<class T1, class E1, class E2>
374   friend constexpr bool operator==(const unexpected<E2>&, const expected<T1, E1>&);
375   template<class T1, class E1, class E2>
376   friend constexpr bool operator!=(const expected<T1, E1>&, const unexpected<E2>&);
377   template<class T1, class E1, class E2>
378   friend constexpr bool operator!=(const unexpected<E2>&, const expected<T1, E1>&);
379 
380   // Specialized algorithms
381   template<class T1, class E1>
382   friend void swap(expected<T1, E1>& x, expected<T1, E1>& y) noexcept(noexcept(x.swap(y)));
383 
384  private:
385   std::variant<value_type, unexpected_type> var_;
386 };
387 
388 template<class T1, class E1, class T2, class E2>
389 constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
390   if (x.has_value() != y.has_value()) return false;
391   if (!x.has_value()) return x.error() == y.error();
392   return *x == *y;
393 }
394 
395 template<class T1, class E1, class T2, class E2>
396 constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y) {
397   return !(x == y);
398 }
399 
400 // Comparison with unexpected<E>
401 template<class T1, class E1, class E2>
402 constexpr bool operator==(const expected<T1, E1>& x, const unexpected<E2>& y) {
403   return !x.has_value() && (x.error() == y.value());
404 }
405 template<class T1, class E1, class E2>
406 constexpr bool operator==(const unexpected<E2>& x, const expected<T1, E1>& y) {
407   return !y.has_value() && (x.value() == y.error());
408 }
409 template<class T1, class E1, class E2>
410 constexpr bool operator!=(const expected<T1, E1>& x, const unexpected<E2>& y) {
411   return x.has_value() || (x.error() != y.value());
412 }
413 template<class T1, class E1, class E2>
414 constexpr bool operator!=(const unexpected<E2>& x, const expected<T1, E1>& y) {
415   return y.has_value() || (x.value() != y.error());
416 }
417 
418 template<class T1, class E1>
swap(expected<T1,E1> & x,expected<T1,E1> & y)419 void swap(expected<T1, E1>& x, expected<T1, E1>& y) noexcept(noexcept(x.swap(y))) {
420   x.swap(y);
421 }
422 
423 template<class E>
424 class _NODISCARD_ expected<void, E> {
425  public:
426   using value_type = void;
427   using error_type = E;
428   using unexpected_type = unexpected<E>;
429 
430   // constructors
431   constexpr expected() = default;
432   constexpr expected(const expected& rhs) = default;
433   constexpr expected(expected&& rhs) noexcept = default;
434 
435   template<class U, class G _ENABLE_IF(
436     std::is_void_v<U> &&
437     std::is_convertible_v<const G&, E> /* non-explicit */
438   )>
439   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const expected<U,G> & rhs)440   constexpr expected(const expected<U, G>& rhs) {
441     if (!rhs.has_value()) var_ = unexpected(rhs.error());
442   }
443 
444   template<class U, class G _ENABLE_IF(
445     std::is_void_v<U> &&
446     !std::is_convertible_v<const G&, E> /* explicit */
447   )>
expected(const expected<U,G> & rhs)448   constexpr explicit expected(const expected<U, G>& rhs) {
449     if (!rhs.has_value()) var_ = unexpected(rhs.error());
450   }
451 
452   template<class U, class G _ENABLE_IF(
453     std::is_void_v<U> &&
454     std::is_convertible_v<const G&&, E> /* non-explicit */
455   )>
456   // NOLINTNEXTLINE(google-explicit-constructor)
expected(expected<U,G> && rhs)457   constexpr expected(expected<U, G>&& rhs) {
458     if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
459   }
460 
461   template<class U, class G _ENABLE_IF(
462     std::is_void_v<U> &&
463     !std::is_convertible_v<const G&&, E> /* explicit */
464   )>
expected(expected<U,G> && rhs)465   constexpr explicit expected(expected<U, G>&& rhs) {
466     if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
467   }
468 
469   template<class G = E _ENABLE_IF(
470     std::is_constructible_v<E, const G&> &&
471     std::is_convertible_v<const G&, E> /* non-explicit */
472   )>
473   // NOLINTNEXTLINE(google-explicit-constructor)
expected(const unexpected<G> & e)474   constexpr expected(const unexpected<G>& e)
475   : var_(std::in_place_index<1>, e.value()) {}
476 
477   template<class G = E _ENABLE_IF(
478     std::is_constructible_v<E, const G&> &&
479     !std::is_convertible_v<const G&, E> /* explicit */
480   )>
expected(const unexpected<G> & e)481   constexpr explicit expected(const unexpected<G>& e)
482   : var_(std::in_place_index<1>, E(e.value())) {}
483 
484   template<class G = E _ENABLE_IF(
485     std::is_constructible_v<E, G&&> &&
486     std::is_convertible_v<G&&, E> /* non-explicit */
487   )>
488   // NOLINTNEXTLINE(google-explicit-constructor)
expected(unexpected<G> && e)489   constexpr expected(unexpected<G>&& e)
490   : var_(std::in_place_index<1>, std::move(e.value())) {}
491 
492   template<class G = E _ENABLE_IF(
493     std::is_constructible_v<E, G&&> &&
494     !std::is_convertible_v<G&&, E> /* explicit */
495   )>
expected(unexpected<G> && e)496   constexpr explicit expected(unexpected<G>&& e)
497   : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
498 
499   template<class... Args _ENABLE_IF(
500     sizeof...(Args) == 0
501   )>
expected(std::in_place_t,Args &&...)502   constexpr explicit expected(std::in_place_t, Args&&...) {}
503 
504   template<class... Args _ENABLE_IF(
505     std::is_constructible_v<E, Args...>
506   )>
expected(unexpect_t,Args &&...args)507   constexpr explicit expected(unexpect_t, Args&&... args)
508   : var_(unexpected_type(std::forward<Args>(args)...)) {}
509 
510   template<class U, class... Args _ENABLE_IF(
511     std::is_constructible_v<E, std::initializer_list<U>&, Args...>
512   )>
expected(unexpect_t,std::initializer_list<U> il,Args &&...args)513   constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
514   : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
515 
516   // destructor
517   ~expected() = default;
518 
519   // assignment
520   // Note: SFNAIE doesn't work here because assignment operator should be
521   // non-template. We could workaround this by defining a templated parent class
522   // having the assignment operator. This incomplete implementation however
523   // doesn't allow us to copy assign expected<T,E> even when T is non-copy
524   // assignable. The copy assignment will fail by the underlying std::variant
525   // anyway though the error message won't be clear.
526   expected& operator=(const expected& rhs) = default;
527 
528   // Note for SFNAIE above applies to here as well
529   expected& operator=(expected&& rhs) noexcept(std::is_nothrow_move_assignable_v<E>) = default;
530 
531   template<class G = E>
532   expected& operator=(const unexpected<G>& rhs) {
533     var_ = rhs;
534     return *this;
535   }
536 
537   template<class G = E _ENABLE_IF(
538     std::is_nothrow_move_constructible_v<G> &&
539     std::is_move_assignable_v<G>
540   )>
541   expected& operator=(unexpected<G>&& rhs) {
542     var_ = std::move(rhs);
543     return *this;
544   }
545 
546   // modifiers
emplace()547   void emplace() {
548     var_ = std::monostate();
549   }
550 
551   // swap
552   template<typename = std::enable_if_t<
553     std::is_swappable_v<E>>
554   >
swap(expected & rhs)555   void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<E>) {
556     var_.swap(rhs.var_);
557   }
558 
559   // observers
has_value()560   constexpr bool has_value() const noexcept { return var_.index() == 0; }
ok()561   constexpr bool ok() const noexcept { return has_value(); }
562 
value()563   constexpr void value() const& { if (!has_value()) std::get<0>(var_); }
564 
error()565   constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
error()566   constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
error()567   constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
error()568   constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
569 
570   // expected equality operators
571   template<class E1, class E2>
572   friend constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y);
573 
574   // Specialized algorithms
575   template<class T1, class E1>
576   friend void swap(expected<T1, E1>& x, expected<T1, E1>& y) noexcept(noexcept(x.swap(y)));
577 
578  private:
579   std::variant<std::monostate, unexpected_type> var_;
580 };
581 
582 template<class E1, class E2>
583 constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y) {
584   if (x.has_value() != y.has_value()) return false;
585   if (!x.has_value()) return x.error() == y.error();
586   return true;
587 }
588 
589 template<class T1, class E1, class E2>
590 constexpr bool operator==(const expected<T1, E1>& x, const expected<void, E2>& y) {
591   if (x.has_value() != y.has_value()) return false;
592   if (!x.has_value()) return x.error() == y.error();
593   return false;
594 }
595 
596 template<class E1, class T2, class E2>
597 constexpr bool operator==(const expected<void, E1>& x, const expected<T2, E2>& y) {
598   if (x.has_value() != y.has_value()) return false;
599   if (!x.has_value()) return x.error() == y.error();
600   return false;
601 }
602 
603 template<class E>
604 class unexpected {
605  public:
606   // constructors
607   constexpr unexpected(const unexpected&) = default;
608   constexpr unexpected(unexpected&&) noexcept(std::is_nothrow_move_constructible_v<E>) = default;
609 
610   template <class Err = E _ENABLE_IF(
611                 std::is_constructible_v<E, Err> &&
612                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
613                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
614   // NOLINTNEXTLINE(google-explicit-constructor,bugprone-forwarding-reference-overload)
unexpected(Err && e)615   constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
616 
617   template<class U, class... Args _ENABLE_IF(
618     std::is_constructible_v<E, std::initializer_list<U>&, Args...>
619   )>
unexpected(std::in_place_t,std::initializer_list<U> il,Args &&...args)620   constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
621   : val_(il, std::forward<Args>(args)...) {}
622 
623   template<class Err _ENABLE_IF(
624     std::is_constructible_v<E, Err> &&
625     !std::is_constructible_v<E, unexpected<Err>&> &&
626     !std::is_constructible_v<E, unexpected<Err>> &&
627     !std::is_constructible_v<E, const unexpected<Err>&> &&
628     !std::is_constructible_v<E, const unexpected<Err>> &&
629     !std::is_convertible_v<unexpected<Err>&, E> &&
630     !std::is_convertible_v<unexpected<Err>, E> &&
631     !std::is_convertible_v<const unexpected<Err>&, E> &&
632     !std::is_convertible_v<const unexpected<Err>, E> &&
633     std::is_convertible_v<Err, E> /* non-explicit */
634   )>
635   // NOLINTNEXTLINE(google-explicit-constructor)
unexpected(const unexpected<Err> & rhs)636   constexpr unexpected(const unexpected<Err>& rhs)
637   : val_(rhs.value()) {}
638 
639   template<class Err _ENABLE_IF(
640     std::is_constructible_v<E, Err> &&
641     !std::is_constructible_v<E, unexpected<Err>&> &&
642     !std::is_constructible_v<E, unexpected<Err>> &&
643     !std::is_constructible_v<E, const unexpected<Err>&> &&
644     !std::is_constructible_v<E, const unexpected<Err>> &&
645     !std::is_convertible_v<unexpected<Err>&, E> &&
646     !std::is_convertible_v<unexpected<Err>, E> &&
647     !std::is_convertible_v<const unexpected<Err>&, E> &&
648     !std::is_convertible_v<const unexpected<Err>, E> &&
649     !std::is_convertible_v<Err, E> /* explicit */
650   )>
unexpected(const unexpected<Err> & rhs)651   constexpr explicit unexpected(const unexpected<Err>& rhs)
652   : val_(E(rhs.value())) {}
653 
654   template<class Err _ENABLE_IF(
655     std::is_constructible_v<E, Err> &&
656     !std::is_constructible_v<E, unexpected<Err>&> &&
657     !std::is_constructible_v<E, unexpected<Err>> &&
658     !std::is_constructible_v<E, const unexpected<Err>&> &&
659     !std::is_constructible_v<E, const unexpected<Err>> &&
660     !std::is_convertible_v<unexpected<Err>&, E> &&
661     !std::is_convertible_v<unexpected<Err>, E> &&
662     !std::is_convertible_v<const unexpected<Err>&, E> &&
663     !std::is_convertible_v<const unexpected<Err>, E> &&
664     std::is_convertible_v<Err, E> /* non-explicit */
665   )>
666   // NOLINTNEXTLINE(google-explicit-constructor)
unexpected(unexpected<Err> && rhs)667   constexpr unexpected(unexpected<Err>&& rhs)
668   : val_(std::move(rhs.value())) {}
669 
670   template<class Err _ENABLE_IF(
671     std::is_constructible_v<E, Err> &&
672     !std::is_constructible_v<E, unexpected<Err>&> &&
673     !std::is_constructible_v<E, unexpected<Err>> &&
674     !std::is_constructible_v<E, const unexpected<Err>&> &&
675     !std::is_constructible_v<E, const unexpected<Err>> &&
676     !std::is_convertible_v<unexpected<Err>&, E> &&
677     !std::is_convertible_v<unexpected<Err>, E> &&
678     !std::is_convertible_v<const unexpected<Err>&, E> &&
679     !std::is_convertible_v<const unexpected<Err>, E> &&
680     !std::is_convertible_v<Err, E> /* explicit */
681   )>
unexpected(unexpected<Err> && rhs)682   constexpr explicit unexpected(unexpected<Err>&& rhs)
683   : val_(E(std::move(rhs.value()))) {}
684 
685   // assignment
686   constexpr unexpected& operator=(const unexpected&) = default;
687   constexpr unexpected& operator=(unexpected&&) noexcept(std::is_nothrow_move_assignable_v<E>) =
688       default;
689   template<class Err = E>
690   constexpr unexpected& operator=(const unexpected<Err>& rhs) {
691     val_ = rhs.value();
692     return *this;
693   }
694   template<class Err = E>
695   constexpr unexpected& operator=(unexpected<Err>&& rhs) {
696     val_ = std::forward<E>(rhs.value());
697     return *this;
698   }
699 
700   // observer
value()701   constexpr const E& value() const& noexcept { return val_; }
value()702   constexpr E& value() & noexcept { return val_; }
value()703   constexpr const E&& value() const&& noexcept { return std::move(val_); }
value()704   constexpr E&& value() && noexcept { return std::move(val_); }
705 
swap(unexpected & other)706   void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
707     std::swap(val_, other.val_);
708   }
709 
710   template<class E1, class E2>
711   friend constexpr bool
712   operator==(const unexpected<E1>& e1, const unexpected<E2>& e2);
713   template<class E1, class E2>
714   friend constexpr bool
715   operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2);
716 
717   template<class E1>
718   friend void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y)));
719 
720  private:
721   E val_;
722 };
723 
724 template<class E1, class E2>
725 constexpr bool
726 operator==(const unexpected<E1>& e1, const unexpected<E2>& e2) {
727   return e1.value() == e2.value();
728 }
729 
730 template<class E1, class E2>
731 constexpr bool
732 operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2) {
733   return e1.value() != e2.value();
734 }
735 
736 template<class E1>
swap(unexpected<E1> & x,unexpected<E1> & y)737 void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y))) {
738   x.swap(y);
739 }
740 
741 // TODO: bad_expected_access class
742 
743 #undef _ENABLE_IF
744 #undef _NODISCARD_
745 
746 }  // namespace base
747 }  // namespace android
748