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