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