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