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