1 // Copyright 2022 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TYPES_EXPECTED_H_ 6 #define BASE_TYPES_EXPECTED_H_ 7 8 #include <type_traits> 9 #include <utility> 10 11 #include "base/check.h" 12 #include "base/types/expected_internal.h" // IWYU pragma: export 13 #include "third_party/abseil-cpp/absl/utility/utility.h" 14 15 // Class template `expected<T, E>` is a vocabulary type which contains an 16 // expected value of type `T`, or an error `E`. The class skews towards behaving 17 // like a `T`, because its intended use is when the expected type is contained. 18 // When something unexpected occurs, more typing is required. When all is good, 19 // code mostly looks as if a `T` were being handled. 20 // 21 // Class template `expected<T, E>` contains either: 22 // * A value of type `T`, the expected value type; or 23 // * A value of type `E`, an error type used when an unexpected outcome 24 // occurred. 25 // 26 // The interface can be queried as to whether the underlying value is the 27 // expected value (of type `T`) or an unexpected value (of type `E`). The 28 // interface and the rational are based on `std::optional`. We consider 29 // `expected<T, E>` as a supplement to `optional<T>`, expressing why an expected 30 // value isn’t contained in the object. 31 // 32 // Example Usage: 33 // 34 // Before: 35 // bool ParseInt32(base::StringPiece input, 36 // int32_t* output, 37 // ParseIntError* error); 38 // ... 39 // 40 // int32_t output; 41 // ParseIntError error; 42 // if (ParseInt32("...". &output, &error)) { 43 // // process `output` 44 // } else { 45 // // process `error` 46 // } 47 // 48 // After: 49 // 50 // base::expected<int32_t, ParseIntError> ParseInt32(base::StringPiece input); 51 // ... 52 // 53 // if (auto parsed = ParseInt32("..."); parsed.has_value()) { 54 // // process `parsed.value()` 55 // } else { 56 // // process `parsed.error()` 57 // } 58 // 59 // References: 60 // * https://wg21.link/P0323 61 // * https://eel.is/c++draft/expected 62 namespace base { 63 64 // Note: base::unexpected and base::expected are C++17 compatible backports of 65 // C++23's std::unexpected and std::expected. They differ from the standard in 66 // the following ways: 67 // 68 // * Not all member functions can be used in a constexpr context. This is due to 69 // limitations in both the C++17 language and the Abseil library used for the 70 // implementation. 71 // * Since Chromium does not support exceptions, there is no bad_expected_access 72 // exception and the program will just terminate when the exception would have 73 // been thrown. Furthermore, all member functions are marked noexcept. 74 // * C++23 allows an implicit conversion from U to expected<T, E> if U is 75 // implicitly convertible to T; the Chromium version only allows an implicit 76 // conversion if U is implicitly convertible to T *and* U is *not* implicitly 77 // convertible to E, to guard against bug-prone patterns such as: 78 // // creates an expected value containing true, not an unexpected value 79 // // containing 123L. 80 // expected<bool, long> e = 123L; 81 // * Because of the above restriction, the Chromium version also introduces 82 // `base::ok` as a complement to `base::unexpected` to simplify returning 83 // success values when the implicit conversion above is disallowed. 84 // * Calling operator* or operator-> on an unexpected value results in program 85 // termination, and not UB. 86 // * There is no operator bool due to bug-prone usage when the value type is 87 // convertible to bool, see e.g. https://abseil.io/tips/141. 88 // * Moving out of an expected object will put it into a moved-from state. 89 // Trying to use it before re-initializing it will result in program 90 // termination. 91 // * The expected<void> specialization is done via a defaulted boolean template 92 // parameter, due to the lack of requires clauses in C++17. 93 // * Since equality operators can not be defaulted in C++17, equality and 94 // inequality operators are specified explicitly. 95 // * base::expected implements the monadic interface proposal 96 // (https://wg21.link/P2505), which is currently only on track for C++26. 97 98 // Class template used as a type hint for constructing a `base::expected` 99 // containing a value (i.e. success). Useful when implicit conversion 100 // construction of `base::expected` is disallowed, e.g. due to ambiguity. 101 // Example usage: 102 // 103 // base::expected<std::string, std::string> RunOp() { 104 // std::string error; 105 // std::string result = RunOpImpl(..., &error); 106 // if (!error.empty()) { 107 // return base::unexpected(std::move(error)); 108 // 109 // // The C++23 std::expected proposal allows this to be simply written as 110 // // return result; 111 // // 112 // // However, the Chromium version disallows this if E implicitly converts 113 // // to T, so without base::ok(), this would have to be written as: 114 // // return base::expected<std::string, std::string>(std::move(result)); 115 // 116 // return base::ok(std::move(result)); 117 // } 118 template <typename T> 119 class ok<T, /* is_void_v<T> = */ false> { 120 public: 121 template <typename U = T, internal::EnableIfOkValueConstruction<T, U> = 0> ok(U && val)122 constexpr explicit ok(U&& val) noexcept : value_(std::forward<U>(val)) {} 123 124 template <typename... Args> ok(absl::in_place_t,Args &&...args)125 constexpr explicit ok(absl::in_place_t, Args&&... args) noexcept 126 : value_(std::forward<Args>(args)...) {} 127 128 template <typename U, typename... Args> ok(absl::in_place_t,std::initializer_list<U> il,Args &&...args)129 constexpr explicit ok(absl::in_place_t, 130 std::initializer_list<U> il, 131 Args&&... args) noexcept 132 : value_(il, std::forward<Args>(args)...) {} 133 value()134 constexpr T& value() & noexcept { return value_; } value()135 constexpr const T& value() const& noexcept { return value_; } value()136 constexpr T&& value() && noexcept { return std::move(value()); } value()137 constexpr const T&& value() const&& noexcept { return std::move(value()); } 138 swap(ok & other)139 constexpr void swap(ok& other) noexcept { 140 using std::swap; 141 swap(value(), other.value()); 142 } 143 swap(ok & x,ok & y)144 friend constexpr void swap(ok& x, ok& y) noexcept { x.swap(y); } 145 146 private: 147 T value_; 148 }; 149 150 template <typename T> 151 class ok<T, /* is_void_v<T> = */ true> { 152 public: 153 constexpr explicit ok() noexcept = default; 154 }; 155 156 template <typename T, typename U> 157 constexpr bool operator==(const ok<T>& lhs, const ok<U>& rhs) noexcept { 158 return lhs.value() == rhs.value(); 159 } 160 161 template <typename T, typename U> 162 constexpr bool operator!=(const ok<T>& lhs, const ok<U>& rhs) noexcept { 163 return !(lhs == rhs); 164 } 165 166 template <typename T> 167 ok(T) -> ok<T>; 168 169 ok()->ok<void>; 170 171 // [expected.un.object], class template unexpected 172 // https://eel.is/c++draft/expected#un.object 173 template <typename E> 174 class unexpected { 175 public: 176 // [expected.un.ctor] Constructors 177 template <typename Err = E, 178 internal::EnableIfUnexpectedValueConstruction<E, Err> = 0> unexpected(Err && err)179 constexpr explicit unexpected(Err&& err) noexcept 180 : error_(std::forward<Err>(err)) {} 181 182 template <typename... Args> unexpected(absl::in_place_t,Args &&...args)183 constexpr explicit unexpected(absl::in_place_t, Args&&... args) noexcept 184 : error_(std::forward<Args>(args)...) {} 185 186 template <typename U, typename... Args> unexpected(absl::in_place_t,std::initializer_list<U> il,Args &&...args)187 constexpr explicit unexpected(absl::in_place_t, 188 std::initializer_list<U> il, 189 Args&&... args) noexcept 190 : error_(il, std::forward<Args>(args)...) {} 191 192 // [expected.un.obs] Observers error()193 constexpr E& error() & noexcept { return error_; } error()194 constexpr const E& error() const& noexcept { return error_; } error()195 constexpr E&& error() && noexcept { return std::move(error()); } error()196 constexpr const E&& error() const&& noexcept { return std::move(error()); } 197 198 // [expected.un.swap] Swap swap(unexpected & other)199 constexpr void swap(unexpected& other) noexcept { 200 using std::swap; 201 swap(error(), other.error()); 202 } 203 swap(unexpected & x,unexpected & y)204 friend constexpr void swap(unexpected& x, unexpected& y) noexcept { 205 x.swap(y); 206 } 207 208 private: 209 E error_; 210 }; 211 212 // [expected.un.eq] Equality operator 213 template <typename E, typename G> 214 constexpr bool operator==(const unexpected<E>& lhs, 215 const unexpected<G>& rhs) noexcept { 216 return lhs.error() == rhs.error(); 217 } 218 219 template <typename E, typename G> 220 constexpr bool operator!=(const unexpected<E>& lhs, 221 const unexpected<G>& rhs) noexcept { 222 return !(lhs == rhs); 223 } 224 225 template <typename E> 226 unexpected(E) -> unexpected<E>; 227 228 // [expected.expected], class template expected 229 // https://eel.is/c++draft/expected#expected 230 template <typename T, typename E> 231 class [[nodiscard]] expected<T, E, /* is_void_v<T> = */ false> { 232 // Note: A partial specialization for void value types follows below. 233 static_assert(!std::is_void_v<T>, "Error: T must not be void"); 234 235 public: 236 using value_type = T; 237 using error_type = E; 238 using unexpected_type = unexpected<E>; 239 240 // Alias template to explicitly opt into the std::pointer_traits machinery. 241 // See e.g. https://en.cppreference.com/w/cpp/memory/pointer_traits#Notes 242 template <typename U> 243 using rebind = expected<U, E>; 244 245 template <typename U, typename G, bool IsVoid> 246 friend class expected; 247 248 // [expected.object.ctor], constructors 249 constexpr expected() noexcept = default; 250 251 // Converting copy and move constructors. These constructors are explicit if 252 // either the value or error type is not implicitly convertible from `rhs`'s 253 // corresponding type. 254 template <typename U, 255 typename G, 256 internal::EnableIfExplicitConversion<T, E, const U&, const G&> = 0> expected(const expected<U,G> & rhs)257 explicit constexpr expected(const expected<U, G>& rhs) noexcept 258 : impl_(rhs.impl_) {} 259 260 template <typename U, 261 typename G, 262 internal::EnableIfImplicitConversion<T, E, const U&, const G&> = 0> 263 // NOLINTNEXTLINE(google-explicit-constructor) expected(const expected<U,G> & rhs)264 /* implicit */ constexpr expected(const expected<U, G>& rhs) noexcept 265 : impl_(rhs.impl_) {} 266 267 template <typename U, 268 typename G, 269 internal::EnableIfExplicitConversion<T, E, U, G> = 0> expected(expected<U,G> && rhs)270 explicit constexpr expected(expected<U, G>&& rhs) noexcept 271 : impl_(std::move(rhs.impl_)) {} 272 273 template <typename U, 274 typename G, 275 internal::EnableIfImplicitConversion<T, E, U, G> = 0> 276 // NOLINTNEXTLINE(google-explicit-constructor) expected(expected<U,G> && rhs)277 /* implicit */ constexpr expected(expected<U, G>&& rhs) noexcept 278 : impl_(std::move(rhs.impl_)) {} 279 280 // Deviation from the Standard, which allows implicit conversions as long as U 281 // is implicitly convertible to T: Chromium additionally requires that U is 282 // not implicitly convertible to E. 283 template <typename U = T, 284 internal::EnableIfExplicitValueConstruction<T, E, U> = 0> expected(U && v)285 explicit constexpr expected(U&& v) noexcept 286 : impl_(kValTag, std::forward<U>(v)) {} 287 288 template <typename U = T, 289 internal::EnableIfImplicitValueConstruction<T, E, U> = 0> 290 // NOLINTNEXTLINE(google-explicit-constructor) expected(U && v)291 /* implicit */ constexpr expected(U&& v) noexcept 292 : impl_(kValTag, std::forward<U>(v)) {} 293 294 template <typename U, internal::EnableIfExplicitConstruction<T, const U&> = 0> expected(const ok<U> & o)295 explicit constexpr expected(const ok<U>& o) noexcept 296 : impl_(kValTag, o.value()) {} 297 298 template <typename U, internal::EnableIfImplicitConstruction<T, const U&> = 0> 299 // NOLINTNEXTLINE(google-explicit-constructor) expected(const ok<U> & o)300 /* implicit */ constexpr expected(const ok<U>& o) noexcept 301 : impl_(kValTag, o.value()) {} 302 303 template <typename U, internal::EnableIfExplicitConstruction<T, U> = 0> expected(ok<U> && o)304 explicit constexpr expected(ok<U>&& o) noexcept 305 : impl_(kValTag, std::move(o.value())) {} 306 307 template <typename U, internal::EnableIfImplicitConstruction<T, U> = 0> 308 // NOLINTNEXTLINE(google-explicit-constructor) expected(ok<U> && o)309 /* implicit */ constexpr expected(ok<U>&& o) noexcept 310 : impl_(kValTag, std::move(o.value())) {} 311 312 template <typename G, internal::EnableIfExplicitConstruction<E, const G&> = 0> expected(const unexpected<G> & e)313 explicit constexpr expected(const unexpected<G>& e) noexcept 314 : impl_(kErrTag, e.error()) {} 315 316 template <typename G, internal::EnableIfImplicitConstruction<E, const G&> = 0> 317 // NOLINTNEXTLINE(google-explicit-constructor) expected(const unexpected<G> & e)318 /* implicit */ constexpr expected(const unexpected<G>& e) noexcept 319 : impl_(kErrTag, e.error()) {} 320 321 template <typename G, internal::EnableIfExplicitConstruction<E, G> = 0> expected(unexpected<G> && e)322 explicit constexpr expected(unexpected<G>&& e) noexcept 323 : impl_(kErrTag, std::move(e.error())) {} 324 325 template <typename G, internal::EnableIfImplicitConstruction<E, G> = 0> 326 // NOLINTNEXTLINE(google-explicit-constructor) expected(unexpected<G> && e)327 /* implicit */ constexpr expected(unexpected<G>&& e) noexcept 328 : impl_(kErrTag, std::move(e.error())) {} 329 330 template <typename... Args> expected(absl::in_place_t,Args &&...args)331 constexpr explicit expected(absl::in_place_t, Args&&... args) noexcept 332 : impl_(kValTag, std::forward<Args>(args)...) {} 333 334 template <typename U, typename... Args> expected(absl::in_place_t,std::initializer_list<U> il,Args &&...args)335 constexpr explicit expected(absl::in_place_t, 336 std::initializer_list<U> il, 337 Args&&... args) noexcept 338 : impl_(kValTag, il, std::forward<Args>(args)...) {} 339 340 template <typename... Args> expected(unexpect_t,Args &&...args)341 constexpr explicit expected(unexpect_t, Args&&... args) noexcept 342 : impl_(kErrTag, std::forward<Args>(args)...) {} 343 344 template <typename U, typename... Args> expected(unexpect_t,std::initializer_list<U> il,Args &&...args)345 constexpr explicit expected(unexpect_t, 346 std::initializer_list<U> il, 347 Args&&... args) noexcept 348 : impl_(kErrTag, il, std::forward<Args>(args)...) {} 349 350 // [expected.object.assign], assignment 351 template <typename U = T, internal::EnableIfValueAssignment<T, E, U> = 0> 352 constexpr expected& operator=(U&& v) noexcept { 353 emplace(std::forward<U>(v)); 354 return *this; 355 } 356 357 template <typename U> 358 constexpr expected& operator=(const ok<U>& o) noexcept { 359 emplace(o.value()); 360 return *this; 361 } 362 363 template <typename U> 364 constexpr expected& operator=(ok<U>&& o) noexcept { 365 emplace(std::move(o.value())); 366 return *this; 367 } 368 369 template <typename G> 370 constexpr expected& operator=(const unexpected<G>& e) noexcept { 371 impl_.emplace_error(e.error()); 372 return *this; 373 } 374 375 template <typename G> 376 constexpr expected& operator=(unexpected<G>&& e) noexcept { 377 impl_.emplace_error(std::move(e.error())); 378 return *this; 379 } 380 381 template <typename... Args> emplace(Args &&...args)382 constexpr T& emplace(Args&&... args) noexcept { 383 return impl_.emplace_value(std::forward<Args>(args)...); 384 } 385 386 template <typename U, typename... Args> emplace(std::initializer_list<U> il,Args &&...args)387 constexpr T& emplace(std::initializer_list<U> il, Args&&... args) noexcept { 388 return impl_.emplace_value(il, std::forward<Args>(args)...); 389 } 390 391 // [expected.object.swap], swap swap(expected & rhs)392 constexpr void swap(expected& rhs) noexcept { impl_.swap(rhs.impl_); } swap(expected & x,expected & y)393 friend constexpr void swap(expected& x, expected& y) noexcept { x.swap(y); } 394 395 // [expected.object.obs], observers 396 constexpr T* operator->() noexcept { return std::addressof(value()); } 397 constexpr const T* operator->() const noexcept { 398 return std::addressof(value()); 399 } 400 401 constexpr T& operator*() & noexcept { return value(); } 402 constexpr const T& operator*() const& noexcept { return value(); } 403 constexpr T&& operator*() && noexcept { return std::move(value()); } 404 constexpr const T&& operator*() const&& noexcept { 405 return std::move(value()); 406 } 407 408 // Note: Deviation from the Standard: No operator bool due to bug-prone 409 // patterns when the value type is convertible to bool, see e.g. 410 // https://abseil.io/tips/141. has_value()411 constexpr bool has_value() const noexcept { return impl_.has_value(); } 412 value()413 constexpr T& value() & noexcept { return impl_.value(); } value()414 constexpr const T& value() const& noexcept { return impl_.value(); } value()415 constexpr T&& value() && noexcept { return std::move(value()); } value()416 constexpr const T&& value() const&& noexcept { return std::move(value()); } 417 error()418 constexpr E& error() & noexcept { return impl_.error(); } error()419 constexpr const E& error() const& noexcept { return impl_.error(); } error()420 constexpr E&& error() && noexcept { return std::move(error()); } error()421 constexpr const E&& error() const&& noexcept { return std::move(error()); } 422 423 template <typename U> value_or(U && v)424 constexpr T value_or(U&& v) const& noexcept { 425 static_assert(std::is_copy_constructible_v<T>, 426 "expected<T, E>::value_or: T must be copy constructible"); 427 static_assert(std::is_convertible_v<U&&, T>, 428 "expected<T, E>::value_or: U must be convertible to T"); 429 return has_value() ? value() : static_cast<T>(std::forward<U>(v)); 430 } 431 432 template <typename U> value_or(U && v)433 constexpr T value_or(U&& v) && noexcept { 434 static_assert(std::is_move_constructible_v<T>, 435 "expected<T, E>::value_or: T must be move constructible"); 436 static_assert(std::is_convertible_v<U&&, T>, 437 "expected<T, E>::value_or: U must be convertible to T"); 438 return has_value() ? std::move(value()) 439 : static_cast<T>(std::forward<U>(v)); 440 } 441 442 template <typename G> error_or(G && e)443 constexpr E error_or(G&& e) const& noexcept { 444 static_assert(std::is_copy_constructible_v<E>, 445 "expected<T, E>::error_or: E must be copy constructible"); 446 static_assert(std::is_convertible_v<G&&, E>, 447 "expected<T, E>::error_or: G must be convertible to E"); 448 return has_value() ? static_cast<E>(std::forward<G>(e)) : error(); 449 } 450 451 template <typename G> error_or(G && e)452 constexpr E error_or(G&& e) && noexcept { 453 static_assert(std::is_move_constructible_v<E>, 454 "expected<T, E>::error_or: E must be move constructible"); 455 static_assert(std::is_convertible_v<G&&, E>, 456 "expected<T, E>::error_or: G must be convertible to E"); 457 return has_value() ? static_cast<E>(std::forward<G>(e)) 458 : std::move(error()); 459 } 460 461 // [expected.object.monadic], monadic operations 462 // 463 // This section implements the monadic interface consisting of `and_then`, 464 // `or_else`, `transform` and `transform_error`. 465 466 // `and_then`: This methods accepts a callable `f` that is invoked with 467 // `value()` in case `has_value()` is true. 468 // 469 // `f`'s return type is required to be a (cvref-qualified) specialization of 470 // base::expected with a matching error_type, i.e. it needs to be of the form 471 // base::expected<U, E> cv ref for some U. 472 // 473 // If `has_value()` is false, this is effectively a no-op, and the function 474 // returns base::expected<U, E>(unexpect, std::forward<E>(error())); 475 // 476 // `and_then` is overloaded for all possible forms of const and ref 477 // qualifiers. 478 template <typename F, 479 typename LazyE = E, 480 internal::EnableIfCopyConstructible<LazyE> = 0> and_then(F && f)481 constexpr auto and_then(F&& f) & noexcept { 482 return internal::AndThen(*this, std::forward<F>(f)); 483 } 484 485 template <typename F, 486 typename LazyE = E, 487 internal::EnableIfCopyConstructible<LazyE> = 0> and_then(F && f)488 constexpr auto and_then(F&& f) const& noexcept { 489 return internal::AndThen(*this, std::forward<F>(f)); 490 } 491 492 template <typename F, 493 typename LazyE = E, 494 internal::EnableIfMoveConstructible<LazyE> = 0> and_then(F && f)495 constexpr auto and_then(F&& f) && noexcept { 496 return internal::AndThen(std::move(*this), std::forward<F>(f)); 497 } 498 499 template <typename F, 500 typename LazyE = E, 501 internal::EnableIfMoveConstructible<LazyE> = 0> and_then(F && f)502 constexpr auto and_then(F&& f) const&& noexcept { 503 return internal::AndThen(std::move(*this), std::forward<F>(f)); 504 } 505 506 // `or_else`: This methods accepts a callable `f` that is invoked with 507 // `error()` in case `has_value()` is false. 508 // 509 // `f`'s return type is required to be a (cvref-qualified) specialization of 510 // base::expected with a matching value_type, i.e. it needs to be of the form 511 // base::expected<T, G> cv ref for some G. 512 // 513 // If `has_value()` is true, this is effectively a no-op, and the function 514 // returns base::expected<T, G>(std::forward<T>(value())); 515 // 516 // `or_else` is overloaded for all possible forms of const and ref 517 // qualifiers. 518 template <typename F, 519 typename LazyT = T, 520 internal::EnableIfCopyConstructible<LazyT> = 0> or_else(F && f)521 constexpr auto or_else(F&& f) & noexcept { 522 return internal::OrElse(*this, std::forward<F>(f)); 523 } 524 525 template <typename F, 526 typename LazyT = T, 527 internal::EnableIfCopyConstructible<LazyT> = 0> or_else(F && f)528 constexpr auto or_else(F&& f) const& noexcept { 529 return internal::OrElse(*this, std::forward<F>(f)); 530 } 531 532 template <typename F, 533 typename LazyT = T, 534 internal::EnableIfMoveConstructible<LazyT> = 0> or_else(F && f)535 constexpr auto or_else(F&& f) && noexcept { 536 return internal::OrElse(std::move(*this), std::forward<F>(f)); 537 } 538 539 template <typename F, 540 typename LazyT = T, 541 internal::EnableIfMoveConstructible<LazyT> = 0> or_else(F && f)542 constexpr auto or_else(F&& f) const&& noexcept { 543 return internal::OrElse(std::move(*this), std::forward<F>(f)); 544 } 545 546 template <typename F, 547 typename LazyE = E, 548 internal::EnableIfCopyConstructible<LazyE> = 0> transform(F && f)549 constexpr auto transform(F&& f) & noexcept { 550 return internal::Transform(*this, std::forward<F>(f)); 551 } 552 553 // `transform`: This methods accepts a callable `f` that is invoked with 554 // `value()` in case `has_value()` is true. 555 // 556 // `f`'s return type U needs to be a valid value_type for expected, i.e. any 557 // type for which `remove_cv_t` is either void, or a complete non-array object 558 // type that is not `absl::in_place_t`, `base::unexpect_t`, or a 559 // specialization of `base::ok` or `base::unexpected`. 560 // 561 // Returns an instance of base::expected<remove_cv_t<U>, E> that is 562 // constructed with f(value()) if there is a value, or unexpected(error()) 563 // otherwise. 564 // 565 // `transform` is overloaded for all possible forms of const and ref 566 // qualifiers. 567 template <typename F, 568 typename LazyE = E, 569 internal::EnableIfCopyConstructible<LazyE> = 0> transform(F && f)570 constexpr auto transform(F&& f) const& noexcept { 571 return internal::Transform(*this, std::forward<F>(f)); 572 } 573 574 template <typename F, 575 typename LazyE = E, 576 internal::EnableIfMoveConstructible<LazyE> = 0> transform(F && f)577 constexpr auto transform(F&& f) && noexcept { 578 return internal::Transform(std::move(*this), std::forward<F>(f)); 579 } 580 581 template <typename F, 582 typename LazyE = E, 583 internal::EnableIfMoveConstructible<LazyE> = 0> transform(F && f)584 constexpr auto transform(F&& f) const&& noexcept { 585 return internal::Transform(std::move(*this), std::forward<F>(f)); 586 } 587 588 // `transform_error`: This methods accepts a callable `f` that is invoked with 589 // `error()` in case `has_value()` is false. 590 // 591 // `f`'s return type G needs to be a valid error_type for expected, i.e. any 592 // type for which `remove_cv_t` is a complete non-array object type that is 593 // not `absl::in_place_t`, `base::unexpect_t`, or a specialization of 594 // `base::ok` or `base::unexpected`. 595 // 596 // Returns an instance of base::expected<T, remove_cv_t<G>> that is 597 // constructed with unexpected(f(error())) if there is no value, or value() 598 // otherwise. 599 // 600 // `transform_error` is overloaded for all possible forms of const and ref 601 // qualifiers. 602 template <typename F, 603 typename LazyT = T, 604 internal::EnableIfCopyConstructible<LazyT> = 0> transform_error(F && f)605 constexpr auto transform_error(F&& f) & noexcept { 606 return internal::TransformError(*this, std::forward<F>(f)); 607 } 608 609 template <typename F, 610 typename LazyT = T, 611 internal::EnableIfCopyConstructible<LazyT> = 0> transform_error(F && f)612 constexpr auto transform_error(F&& f) const& noexcept { 613 return internal::TransformError(*this, std::forward<F>(f)); 614 } 615 616 template <typename F, 617 typename LazyT = T, 618 internal::EnableIfMoveConstructible<LazyT> = 0> transform_error(F && f)619 constexpr auto transform_error(F&& f) && noexcept { 620 return internal::TransformError(std::move(*this), std::forward<F>(f)); 621 } 622 623 template <typename F, 624 typename LazyT = T, 625 internal::EnableIfMoveConstructible<LazyT> = 0> transform_error(F && f)626 constexpr auto transform_error(F&& f) const&& noexcept { 627 return internal::TransformError(std::move(*this), std::forward<F>(f)); 628 } 629 630 private: 631 using Impl = internal::ExpectedImpl<T, E>; 632 static constexpr auto kValTag = Impl::kValTag; 633 static constexpr auto kErrTag = Impl::kErrTag; 634 635 Impl impl_; 636 }; 637 638 // [expected.void], partial specialization of expected for void types 639 template <typename T, typename E> 640 class [[nodiscard]] expected<T, E, /* is_void_v<T> = */ true> { 641 // Note: A partial specialization for non-void value types can be found above. 642 static_assert(std::is_void_v<T>, "Error: T must be void"); 643 644 public: 645 using value_type = T; 646 using error_type = E; 647 using unexpected_type = unexpected<E>; 648 649 // Alias template to explicitly opt into the std::pointer_traits machinery. 650 // See e.g. https://en.cppreference.com/w/cpp/memory/pointer_traits#Notes 651 template <typename U> 652 using rebind = expected<U, E>; 653 654 template <typename U, typename G, bool IsVoid> 655 friend class expected; 656 657 // [expected.void.ctor], constructors 658 constexpr expected() noexcept = default; 659 660 // Converting copy and move constructors. These constructors are explicit if 661 // the error type is not implicitly convertible from `rhs`'s error type. 662 template <typename U, 663 typename G, 664 internal::EnableIfExplicitVoidConversion<E, U, const G&> = 0> expected(const expected<U,G> & rhs)665 constexpr explicit expected(const expected<U, G>& rhs) noexcept 666 : impl_(rhs.impl_) {} 667 668 template <typename U, 669 typename G, 670 internal::EnableIfImplicitVoidConversion<E, U, const G&> = 0> 671 // NOLINTNEXTLINE(google-explicit-constructor) expected(const expected<U,G> & rhs)672 constexpr /* implicit */ expected(const expected<U, G>& rhs) noexcept 673 : impl_(rhs.impl_) {} 674 675 template <typename U, 676 typename G, 677 internal::EnableIfExplicitVoidConversion<E, U, G> = 0> expected(expected<U,G> && rhs)678 constexpr explicit expected(expected<U, G>&& rhs) noexcept 679 : impl_(std::move(rhs.impl_)) {} 680 681 template <typename U, 682 typename G, 683 internal::EnableIfImplicitVoidConversion<E, U, G> = 0> 684 // NOLINTNEXTLINE(google-explicit-constructor) expected(expected<U,G> && rhs)685 constexpr /* implicit */ expected(expected<U, G>&& rhs) noexcept 686 : impl_(std::move(rhs.impl_)) {} 687 688 // NOLINTNEXTLINE(google-explicit-constructor) expected(base::ok<T>)689 constexpr /* implicit */ expected(base::ok<T>) noexcept {} 690 691 template <typename G, internal::EnableIfExplicitConstruction<E, const G&> = 0> expected(const unexpected<G> & e)692 explicit constexpr expected(const unexpected<G>& e) noexcept 693 : impl_(kErrTag, e.error()) {} 694 695 template <typename G, internal::EnableIfImplicitConstruction<E, const G&> = 0> 696 // NOLINTNEXTLINE(google-explicit-constructor) expected(const unexpected<G> & e)697 /* implicit */ constexpr expected(const unexpected<G>& e) noexcept 698 : impl_(kErrTag, e.error()) {} 699 700 template <typename G, internal::EnableIfExplicitConstruction<E, G> = 0> expected(unexpected<G> && e)701 explicit constexpr expected(unexpected<G>&& e) noexcept 702 : impl_(kErrTag, std::move(e.error())) {} 703 704 template <typename G, internal::EnableIfImplicitConstruction<E, G> = 0> 705 // NOLINTNEXTLINE(google-explicit-constructor) expected(unexpected<G> && e)706 /* implicit */ constexpr expected(unexpected<G>&& e) noexcept 707 : impl_(kErrTag, std::move(e.error())) {} 708 expected(absl::in_place_t)709 constexpr explicit expected(absl::in_place_t) noexcept {} 710 711 template <typename... Args> expected(unexpect_t,Args &&...args)712 constexpr explicit expected(unexpect_t, Args&&... args) noexcept 713 : impl_(kErrTag, std::forward<Args>(args)...) {} 714 715 template <typename U, typename... Args> expected(unexpect_t,std::initializer_list<U> il,Args &&...args)716 constexpr explicit expected(unexpect_t, 717 std::initializer_list<U> il, 718 Args&&... args) noexcept 719 : impl_(kErrTag, il, std::forward<Args>(args)...) {} 720 721 // [expected.void.assign], assignment 722 template <typename G> 723 constexpr expected& operator=(const unexpected<G>& e) noexcept { 724 impl_.emplace_error(e.error()); 725 return *this; 726 } 727 728 template <typename G> 729 constexpr expected& operator=(unexpected<G>&& e) noexcept { 730 impl_.emplace_error(std::move(e.error())); 731 return *this; 732 } 733 emplace()734 constexpr void emplace() noexcept { impl_.emplace_value(); } 735 736 // [expected.void.swap], swap swap(expected & rhs)737 constexpr void swap(expected& rhs) noexcept { impl_.swap(rhs.impl_); } swap(expected & x,expected & y)738 friend constexpr void swap(expected& x, expected& y) noexcept { x.swap(y); } 739 740 // [expected.void.obs], observers 741 // Note: Deviation from the Standard: No operator bool due to consistency with 742 // non-void expected types. has_value()743 constexpr bool has_value() const noexcept { return impl_.has_value(); } 744 745 constexpr void operator*() const { CHECK(has_value()); } value()746 constexpr void value() const { CHECK(has_value()); } 747 error()748 constexpr E& error() & { return impl_.error(); } error()749 constexpr const E& error() const& { return impl_.error(); } error()750 constexpr E&& error() && { return std::move(error()); } error()751 constexpr const E&& error() const&& { return std::move(error()); } 752 753 template <typename G> error_or(G && e)754 constexpr E error_or(G&& e) const& noexcept { 755 static_assert(std::is_copy_constructible_v<E>, 756 "expected<T, E>::error_or: E must be copy constructible"); 757 static_assert(std::is_convertible_v<G&&, E>, 758 "expected<T, E>::error_or: G must be convertible to E"); 759 return has_value() ? static_cast<E>(std::forward<G>(e)) : error(); 760 } 761 762 template <typename G> error_or(G && e)763 constexpr E error_or(G&& e) && noexcept { 764 static_assert(std::is_move_constructible_v<E>, 765 "expected<T, E>::error_or: E must be move constructible"); 766 static_assert(std::is_convertible_v<G&&, E>, 767 "expected<T, E>::error_or: G must be convertible to E"); 768 return has_value() ? static_cast<E>(std::forward<G>(e)) 769 : std::move(error()); 770 } 771 772 // [expected.void.monadic], monadic operations 773 // 774 // This section implements the monadic interface consisting of `and_then`, 775 // `or_else`, `transform` and `transform_error`. In contrast to the non void 776 // specialization it is mandated that the callables for `and_then` and 777 // `transform`don't take any arguments. 778 779 // `and_then`: This methods accepts a callable `f` that is invoked with 780 // no arguments in case `has_value()` is true. 781 // 782 // `f`'s return type is required to be a (cvref-qualified) specialization of 783 // base::expected with a matching error_type, i.e. it needs to be of the form 784 // base::expected<U, E> cv ref for some U. 785 // 786 // If `has_value()` is false, this is effectively a no-op, and the function 787 // returns base::expected<U, E>(unexpect, std::forward<E>(error())); 788 // 789 // `and_then` is overloaded for all possible forms of const and ref 790 // qualifiers. 791 template <typename F, 792 typename LazyE = E, 793 internal::EnableIfCopyConstructible<LazyE> = 0> and_then(F && f)794 constexpr auto and_then(F&& f) & noexcept { 795 return internal::AndThen(*this, std::forward<F>(f)); 796 } 797 798 template <typename F, 799 typename LazyE = E, 800 internal::EnableIfCopyConstructible<LazyE> = 0> and_then(F && f)801 constexpr auto and_then(F&& f) const& noexcept { 802 return internal::AndThen(*this, std::forward<F>(f)); 803 } 804 805 template <typename F, 806 typename LazyE = E, 807 internal::EnableIfMoveConstructible<LazyE> = 0> and_then(F && f)808 constexpr auto and_then(F&& f) && noexcept { 809 return internal::AndThen(std::move(*this), std::forward<F>(f)); 810 } 811 812 template <typename F, 813 typename LazyE = E, 814 internal::EnableIfMoveConstructible<LazyE> = 0> and_then(F && f)815 constexpr auto and_then(F&& f) const&& noexcept { 816 return internal::AndThen(std::move(*this), std::forward<F>(f)); 817 } 818 819 // `or_else`: This methods accepts a callable `f` that is invoked with 820 // `error()` in case `has_value()` is false. 821 // 822 // `f`'s return type is required to be a (cvref-qualified) specialization of 823 // base::expected with a matching value_type, i.e. it needs to be cv void. 824 // 825 // If `has_value()` is true, this is effectively a no-op, and the function 826 // returns base::expected<cv void, G>(). 827 // 828 // `or_else` is overloaded for all possible forms of const and ref 829 // qualifiers. 830 template <typename F> or_else(F && f)831 constexpr auto or_else(F&& f) & noexcept { 832 return internal::OrElse(*this, std::forward<F>(f)); 833 } 834 835 template <typename F> or_else(F && f)836 constexpr auto or_else(F&& f) const& noexcept { 837 return internal::OrElse(*this, std::forward<F>(f)); 838 } 839 840 template <typename F> or_else(F && f)841 constexpr auto or_else(F&& f) && noexcept { 842 return internal::OrElse(std::move(*this), std::forward<F>(f)); 843 } 844 845 template <typename F> or_else(F && f)846 constexpr auto or_else(F&& f) const&& noexcept { 847 return internal::OrElse(std::move(*this), std::forward<F>(f)); 848 } 849 850 // `transform`: This methods accepts a callable `f` that is invoked with no 851 // arguments in case `has_value()` is true. 852 // 853 // `f`'s return type U needs to be a valid value_type for expected, i.e. any 854 // type for which `remove_cv_t` is either void, or a complete non-array object 855 // type that is not `absl::in_place_t`, `base::unexpect_t`, or a 856 // specialization of `base::ok` or `base::unexpected`. 857 // 858 // Returns an instance of base::expected<remove_cv_t<U>, E> that is 859 // constructed with f() if has_value() is true, or unexpected(error()) 860 // otherwise. 861 // 862 // `transform` is overloaded for all possible forms of const and ref 863 // qualifiers. 864 template <typename F, 865 typename LazyE = E, 866 internal::EnableIfCopyConstructible<LazyE> = 0> transform(F && f)867 constexpr auto transform(F&& f) & noexcept { 868 return internal::Transform(*this, std::forward<F>(f)); 869 } 870 871 template <typename F, 872 typename LazyE = E, 873 internal::EnableIfCopyConstructible<LazyE> = 0> transform(F && f)874 constexpr auto transform(F&& f) const& noexcept { 875 return internal::Transform(*this, std::forward<F>(f)); 876 } 877 878 template <typename F, 879 typename LazyE = E, 880 internal::EnableIfMoveConstructible<LazyE> = 0> transform(F && f)881 constexpr auto transform(F&& f) && noexcept { 882 return internal::Transform(std::move(*this), std::forward<F>(f)); 883 } 884 885 template <typename F, 886 typename LazyE = E, 887 internal::EnableIfMoveConstructible<LazyE> = 0> transform(F && f)888 constexpr auto transform(F&& f) const&& noexcept { 889 return internal::Transform(std::move(*this), std::forward<F>(f)); 890 } 891 892 // `transform_error`: This methods accepts a callable `f` that is invoked with 893 // `error()` in case `has_value()` is false. 894 // 895 // `f`'s return type G needs to be a valid error_type for expected, i.e. any 896 // type for which `remove_cv_t` is a complete non-array object type that is 897 // not `absl::in_place_t`, `base::unexpect_t`, or a specialization of 898 // `base::ok` or `base::unexpected`. 899 // 900 // Returns an instance of base::expected<cv void, remove_cv_t<G>> that is 901 // constructed with unexpected(f(error())) if there is no value, or default 902 // constructed otherwise. 903 // 904 // `transform_error` is overloaded for all possible forms of const and ref 905 // qualifiers. 906 template <typename F> transform_error(F && f)907 constexpr auto transform_error(F&& f) & noexcept { 908 return internal::TransformError(*this, std::forward<F>(f)); 909 } 910 911 template <typename F> transform_error(F && f)912 constexpr auto transform_error(F&& f) const& noexcept { 913 return internal::TransformError(*this, std::forward<F>(f)); 914 } 915 916 template <typename F> transform_error(F && f)917 constexpr auto transform_error(F&& f) && noexcept { 918 return internal::TransformError(std::move(*this), std::forward<F>(f)); 919 } 920 921 template <typename F> transform_error(F && f)922 constexpr auto transform_error(F&& f) const&& noexcept { 923 return internal::TransformError(std::move(*this), std::forward<F>(f)); 924 } 925 926 private: 927 // Note: Since we can't store void types we use absl::monostate instead. 928 using Impl = internal::ExpectedImpl<absl::monostate, E>; 929 static constexpr auto kErrTag = Impl::kErrTag; 930 931 Impl impl_; 932 }; 933 934 // [expected.object.eq], equality operators 935 // [expected.void.eq], equality operators 936 template <typename T, typename E, typename U, typename G, bool IsVoid> 937 constexpr bool operator==(const expected<T, E, IsVoid>& x, 938 const expected<U, G, IsVoid>& y) noexcept { 939 auto equal_values = [](const auto& x, const auto& y) { 940 // Values for expected void types always compare equal. 941 if constexpr (IsVoid) { 942 return true; 943 } else { 944 return x.value() == y.value(); 945 } 946 }; 947 948 return x.has_value() == y.has_value() && 949 (x.has_value() ? equal_values(x, y) : x.error() == y.error()); 950 } 951 952 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 953 constexpr bool operator==(const expected<T, E>& x, const U& v) noexcept { 954 return x.has_value() && x.value() == v; 955 } 956 957 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 958 constexpr bool operator==(const U& v, const expected<T, E>& x) noexcept { 959 return x == v; 960 } 961 962 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 963 constexpr bool operator==(const expected<T, E>& x, const ok<U>& o) noexcept { 964 return x.has_value() && x.value() == o.value(); 965 } 966 967 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 968 constexpr bool operator==(const ok<U>& o, const expected<T, E>& x) noexcept { 969 return x == o; 970 } 971 972 template <typename T, typename E, typename G> 973 constexpr bool operator==(const expected<T, E>& x, 974 const unexpected<G>& e) noexcept { 975 return !x.has_value() && x.error() == e.error(); 976 } 977 978 template <typename T, typename E, typename G> 979 constexpr bool operator==(const unexpected<G>& e, 980 const expected<T, E>& x) noexcept { 981 return x == e; 982 } 983 984 template <typename T, typename E, typename U, typename G, bool IsVoid> 985 constexpr bool operator!=(const expected<T, E, IsVoid>& x, 986 const expected<U, G, IsVoid>& y) noexcept { 987 return !(x == y); 988 } 989 990 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 991 constexpr bool operator!=(const expected<T, E>& x, const U& v) noexcept { 992 return !(x == v); 993 } 994 995 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 996 constexpr bool operator!=(const U& v, const expected<T, E>& x) noexcept { 997 return !(v == x); 998 } 999 1000 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 1001 constexpr bool operator!=(const expected<T, E>& x, const ok<U>& o) noexcept { 1002 return !(x == o); 1003 } 1004 1005 template <typename T, typename E, typename U, internal::EnableIfNotVoid<T> = 0> 1006 constexpr bool operator!=(const ok<U>& o, const expected<T, E>& x) noexcept { 1007 return !(o == x); 1008 } 1009 1010 template <typename T, typename E, typename G> 1011 constexpr bool operator!=(const expected<T, E>& x, 1012 const unexpected<G>& e) noexcept { 1013 return !(x == e); 1014 } 1015 1016 template <typename T, typename E, typename G> 1017 constexpr bool operator!=(const unexpected<G>& e, 1018 const expected<T, E>& x) noexcept { 1019 return !(e == x); 1020 } 1021 1022 } // namespace base 1023 1024 #endif // BASE_TYPES_EXPECTED_H_ 1025