statusor.h (29688B)
1 // Copyright 2020 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: statusor.h 17 // ----------------------------------------------------------------------------- 18 // 19 // An `absl::StatusOr<T>` represents a union of an `absl::Status` object 20 // and an object of type `T`. The `absl::StatusOr<T>` will either contain an 21 // object of type `T` (indicating a successful operation), or an error (of type 22 // `absl::Status`) explaining why such a value is not present. 23 // 24 // In general, check the success of an operation returning an 25 // `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()` 26 // member function. 27 // 28 // Example: 29 // 30 // StatusOr<Foo> result = Calculation(); 31 // if (result.ok()) { 32 // result->DoSomethingCool(); 33 // } else { 34 // LOG(ERROR) << result.status(); 35 // } 36 #ifndef ABSL_STATUS_STATUSOR_H_ 37 #define ABSL_STATUS_STATUSOR_H_ 38 39 #include <exception> 40 #include <initializer_list> 41 #include <new> 42 #include <ostream> 43 #include <string> 44 #include <type_traits> 45 #include <utility> 46 47 #include "absl/base/attributes.h" 48 #include "absl/base/nullability.h" 49 #include "absl/base/call_once.h" 50 #include "absl/meta/type_traits.h" 51 #include "absl/status/internal/statusor_internal.h" 52 #include "absl/status/status.h" 53 #include "absl/strings/has_absl_stringify.h" 54 #include "absl/strings/has_ostream_operator.h" 55 #include "absl/strings/str_format.h" 56 #include "absl/types/variant.h" 57 #include "absl/utility/utility.h" 58 59 namespace absl { 60 ABSL_NAMESPACE_BEGIN 61 62 // BadStatusOrAccess 63 // 64 // This class defines the type of object to throw (if exceptions are enabled), 65 // when accessing the value of an `absl::StatusOr<T>` object that does not 66 // contain a value. This behavior is analogous to that of 67 // `std::bad_optional_access` in the case of accessing an invalid 68 // `std::optional` value. 69 // 70 // Example: 71 // 72 // try { 73 // absl::StatusOr<int> v = FetchInt(); 74 // DoWork(v.value()); // Accessing value() when not "OK" may throw 75 // } catch (absl::BadStatusOrAccess& ex) { 76 // LOG(ERROR) << ex.status(); 77 // } 78 class BadStatusOrAccess : public std::exception { 79 public: 80 explicit BadStatusOrAccess(absl::Status status); 81 ~BadStatusOrAccess() override = default; 82 83 BadStatusOrAccess(const BadStatusOrAccess& other); 84 BadStatusOrAccess& operator=(const BadStatusOrAccess& other); 85 BadStatusOrAccess(BadStatusOrAccess&& other); 86 BadStatusOrAccess& operator=(BadStatusOrAccess&& other); 87 88 // BadStatusOrAccess::what() 89 // 90 // Returns the associated explanatory string of the `absl::StatusOr<T>` 91 // object's error code. This function contains information about the failing 92 // status, but its exact formatting may change and should not be depended on. 93 // 94 // The pointer of this string is guaranteed to be valid until any non-const 95 // function is invoked on the exception object. 96 absl::Nonnull<const char*> what() const noexcept override; 97 98 // BadStatusOrAccess::status() 99 // 100 // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's 101 // error. 102 const absl::Status& status() const; 103 104 private: 105 void InitWhat() const; 106 107 absl::Status status_; 108 mutable absl::once_flag init_what_; 109 mutable std::string what_; 110 }; 111 112 // Returned StatusOr objects may not be ignored. 113 template <typename T> 114 #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) 115 // TODO(b/176172494): ABSL_MUST_USE_RESULT should expand to the more strict 116 // [[nodiscard]]. For now, just use [[nodiscard]] directly when it is available. 117 class [[nodiscard]] StatusOr; 118 #else 119 class ABSL_MUST_USE_RESULT StatusOr; 120 #endif // ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) 121 122 // absl::StatusOr<T> 123 // 124 // The `absl::StatusOr<T>` class template is a union of an `absl::Status` object 125 // and an object of type `T`. The `absl::StatusOr<T>` models an object that is 126 // either a usable object, or an error (of type `absl::Status`) explaining why 127 // such an object is not present. An `absl::StatusOr<T>` is typically the return 128 // value of a function which may fail. 129 // 130 // An `absl::StatusOr<T>` can never hold an "OK" status (an 131 // `absl::StatusCode::kOk` value); instead, the presence of an object of type 132 // `T` indicates success. Instead of checking for a `kOk` value, use the 133 // `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code 134 // readability, that using the `ok()` function is preferred for `absl::Status` 135 // as well.) 136 // 137 // Example: 138 // 139 // StatusOr<Foo> result = DoBigCalculationThatCouldFail(); 140 // if (result.ok()) { 141 // result->DoSomethingCool(); 142 // } else { 143 // LOG(ERROR) << result.status(); 144 // } 145 // 146 // Accessing the object held by an `absl::StatusOr<T>` should be performed via 147 // `operator*` or `operator->`, after a call to `ok()` confirms that the 148 // `absl::StatusOr<T>` holds an object of type `T`: 149 // 150 // Example: 151 // 152 // absl::StatusOr<int> i = GetCount(); 153 // if (i.ok()) { 154 // updated_total += *i; 155 // } 156 // 157 // NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will 158 // throw an exception if exceptions are enabled or terminate the process when 159 // exceptions are not enabled. 160 // 161 // Example: 162 // 163 // StatusOr<Foo> result = DoBigCalculationThatCouldFail(); 164 // const Foo& foo = result.value(); // Crash/exception if no value present 165 // foo.DoSomethingCool(); 166 // 167 // A `absl::StatusOr<T*>` can be constructed from a null pointer like any other 168 // pointer value, and the result will be that `ok()` returns `true` and 169 // `value()` returns `nullptr`. Checking the value of pointer in an 170 // `absl::StatusOr<T*>` generally requires a bit more care, to ensure both that 171 // a value is present and that value is not null: 172 // 173 // StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); 174 // if (!result.ok()) { 175 // LOG(ERROR) << result.status(); 176 // } else if (*result == nullptr) { 177 // LOG(ERROR) << "Unexpected null pointer"; 178 // } else { 179 // (*result)->DoSomethingCool(); 180 // } 181 // 182 // Example factory implementation returning StatusOr<T>: 183 // 184 // StatusOr<Foo> FooFactory::MakeFoo(int arg) { 185 // if (arg <= 0) { 186 // return absl::Status(absl::StatusCode::kInvalidArgument, 187 // "Arg must be positive"); 188 // } 189 // return Foo(arg); 190 // } 191 template <typename T> 192 class StatusOr : private internal_statusor::StatusOrData<T>, 193 private internal_statusor::CopyCtorBase<T>, 194 private internal_statusor::MoveCtorBase<T>, 195 private internal_statusor::CopyAssignBase<T>, 196 private internal_statusor::MoveAssignBase<T> { 197 template <typename U> 198 friend class StatusOr; 199 200 typedef internal_statusor::StatusOrData<T> Base; 201 202 public: 203 // StatusOr<T>::value_type 204 // 205 // This instance data provides a generic `value_type` member for use within 206 // generic programming. This usage is analogous to that of 207 // `optional::value_type` in the case of `std::optional`. 208 typedef T value_type; 209 210 // Constructors 211 212 // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown` 213 // status. This constructor is marked 'explicit' to prevent usages in return 214 // values such as 'return {};', under the misconception that 215 // `absl::StatusOr<std::vector<int>>` will be initialized with an empty 216 // vector, instead of an `absl::StatusCode::kUnknown` error code. 217 explicit StatusOr(); 218 219 // `StatusOr<T>` is copy constructible if `T` is copy constructible. 220 StatusOr(const StatusOr&) = default; 221 // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy 222 // assignable. 223 StatusOr& operator=(const StatusOr&) = default; 224 225 // `StatusOr<T>` is move constructible if `T` is move constructible. 226 StatusOr(StatusOr&&) = default; 227 // `StatusOr<T>` is moveAssignable if `T` is move constructible and move 228 // assignable. 229 StatusOr& operator=(StatusOr&&) = default; 230 231 // Converting Constructors 232 233 // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T` 234 // is constructible from `U`. To avoid ambiguity, these constructors are 235 // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor 236 // is explicit if and only if the corresponding construction of `T` from `U` 237 // is explicit. (This constructor inherits its explicitness from the 238 // underlying constructor.) 239 template <typename U, absl::enable_if_t< 240 internal_statusor::IsConstructionFromStatusOrValid< 241 false, T, U, false, const U&>::value, 242 int> = 0> 243 StatusOr(const StatusOr<U>& other) // NOLINT 244 : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} 245 template <typename U, absl::enable_if_t< 246 internal_statusor::IsConstructionFromStatusOrValid< 247 false, T, U, true, const U&>::value, 248 int> = 0> 249 StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 250 : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} 251 template <typename U, absl::enable_if_t< 252 internal_statusor::IsConstructionFromStatusOrValid< 253 true, T, U, false, const U&>::value, 254 int> = 0> 255 explicit StatusOr(const StatusOr<U>& other) 256 : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} 257 template <typename U, absl::enable_if_t< 258 internal_statusor::IsConstructionFromStatusOrValid< 259 true, T, U, true, const U&>::value, 260 int> = 0> 261 explicit StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND) 262 : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {} 263 264 template <typename U, absl::enable_if_t< 265 internal_statusor::IsConstructionFromStatusOrValid< 266 false, T, U, false, U&&>::value, 267 int> = 0> 268 StatusOr(StatusOr<U>&& other) // NOLINT 269 : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} 270 template <typename U, absl::enable_if_t< 271 internal_statusor::IsConstructionFromStatusOrValid< 272 false, T, U, true, U&&>::value, 273 int> = 0> 274 StatusOr(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 275 : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} 276 template <typename U, absl::enable_if_t< 277 internal_statusor::IsConstructionFromStatusOrValid< 278 true, T, U, false, U&&>::value, 279 int> = 0> 280 explicit StatusOr(StatusOr<U>&& other) 281 : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} 282 template <typename U, absl::enable_if_t< 283 internal_statusor::IsConstructionFromStatusOrValid< 284 true, T, U, true, U&&>::value, 285 int> = 0> 286 explicit StatusOr(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND) 287 : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {} 288 289 // Converting Assignment Operators 290 291 // Creates an `absl::StatusOr<T>` through assignment from an 292 // `absl::StatusOr<U>` when: 293 // 294 // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning 295 // `U` to `T` directly. 296 // * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error 297 // code by destroying `absl::StatusOr<T>`'s value and assigning from 298 // `absl::StatusOr<U>' 299 // * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is 300 // OK by directly initializing `T` from `U`. 301 // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error 302 // code by assigning the `Status` in `absl::StatusOr<U>` to 303 // `absl::StatusOr<T>` 304 // 305 // These overloads only apply if `absl::StatusOr<T>` is constructible and 306 // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly 307 // assigned from `StatusOr<U>`. 308 template <typename U, 309 absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid< 310 T, const U&, false>::value, 311 int> = 0> 312 StatusOr& operator=(const StatusOr<U>& other) { 313 this->Assign(other); 314 return *this; 315 } 316 template <typename U, 317 absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid< 318 T, const U&, true>::value, 319 int> = 0> 320 StatusOr& operator=(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND) { 321 this->Assign(other); 322 return *this; 323 } 324 template <typename U, 325 absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid< 326 T, U&&, false>::value, 327 int> = 0> 328 StatusOr& operator=(StatusOr<U>&& other) { 329 this->Assign(std::move(other)); 330 return *this; 331 } 332 template <typename U, 333 absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid< 334 T, U&&, true>::value, 335 int> = 0> 336 StatusOr& operator=(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND) { 337 this->Assign(std::move(other)); 338 return *this; 339 } 340 341 // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling 342 // this constructor, `this->ok()` will be `false` and calls to `value()` will 343 // crash, or produce an exception if exceptions are enabled. 344 // 345 // The constructor also takes any type `U` that is convertible to 346 // `absl::Status`. This constructor is explicit if an only if `U` is not of 347 // type `absl::Status` and the conversion from `U` to `Status` is explicit. 348 // 349 // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed. 350 // In optimized builds, passing absl::OkStatus() here will have the effect 351 // of passing absl::StatusCode::kInternal as a fallback. 352 template <typename U = absl::Status, 353 absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid< 354 false, T, U>::value, 355 int> = 0> 356 StatusOr(U&& v) : Base(std::forward<U>(v)) {} 357 358 template <typename U = absl::Status, 359 absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid< 360 true, T, U>::value, 361 int> = 0> 362 explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {} 363 template <typename U = absl::Status, 364 absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid< 365 false, T, U>::value, 366 int> = 0> 367 StatusOr& operator=(U&& v) { 368 this->AssignStatus(std::forward<U>(v)); 369 return *this; 370 } 371 372 // Perfect-forwarding value assignment operator. 373 374 // If `*this` contains a `T` value before the call, the contained value is 375 // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized 376 // from `std::forward<U>(v)`. 377 // This function does not participate in overload unless: 378 // 1. `std::is_constructible_v<T, U>` is true, 379 // 2. `std::is_assignable_v<T&, U>` is true. 380 // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false. 381 // 4. Assigning `U` to `T` is not ambiguous: 382 // If `U` is `StatusOr<V>` and `T` is constructible and assignable from 383 // both `StatusOr<V>` and `V`, the assignment is considered bug-prone and 384 // ambiguous thus will fail to compile. For example: 385 // StatusOr<bool> s1 = true; // s1.ok() && *s1 == true 386 // StatusOr<bool> s2 = false; // s2.ok() && *s2 == false 387 // s1 = s2; // ambiguous, `s1 = *s2` or `s1 = bool(s2)`? 388 template <typename U = T, 389 typename std::enable_if< 390 internal_statusor::IsAssignmentValid<T, U, false>::value, 391 int>::type = 0> 392 StatusOr& operator=(U&& v) { 393 this->Assign(std::forward<U>(v)); 394 return *this; 395 } 396 template <typename U = T, 397 typename std::enable_if< 398 internal_statusor::IsAssignmentValid<T, U, true>::value, 399 int>::type = 0> 400 StatusOr& operator=(U&& v ABSL_ATTRIBUTE_LIFETIME_BOUND) { 401 this->Assign(std::forward<U>(v)); 402 return *this; 403 } 404 405 // Constructs the inner value `T` in-place using the provided args, using the 406 // `T(args...)` constructor. 407 template <typename... Args> 408 explicit StatusOr(absl::in_place_t, Args&&... args); 409 template <typename U, typename... Args> 410 explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist, 411 Args&&... args); 412 413 // Constructs the inner value `T` in-place using the provided args, using the 414 // `T(U)` (direct-initialization) constructor. This constructor is only valid 415 // if `T` can be constructed from a `U`. Can accept move or copy constructors. 416 // 417 // This constructor is explicit if `U` is not convertible to `T`. To avoid 418 // ambiguity, this constructor is disabled if `U` is a `StatusOr<J>`, where 419 // `J` is convertible to `T`. 420 template <typename U = T, 421 absl::enable_if_t<internal_statusor::IsConstructionValid< 422 false, T, U, false>::value, 423 int> = 0> 424 StatusOr(U&& u) // NOLINT 425 : StatusOr(absl::in_place, std::forward<U>(u)) {} 426 template <typename U = T, 427 absl::enable_if_t<internal_statusor::IsConstructionValid< 428 false, T, U, true>::value, 429 int> = 0> 430 StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 431 : StatusOr(absl::in_place, std::forward<U>(u)) {} 432 433 template <typename U = T, 434 absl::enable_if_t<internal_statusor::IsConstructionValid< 435 true, T, U, false>::value, 436 int> = 0> 437 explicit StatusOr(U&& u) // NOLINT 438 : StatusOr(absl::in_place, std::forward<U>(u)) {} 439 template <typename U = T, 440 absl::enable_if_t< 441 internal_statusor::IsConstructionValid<true, T, U, true>::value, 442 int> = 0> 443 explicit StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT 444 : StatusOr(absl::in_place, std::forward<U>(u)) {} 445 446 // StatusOr<T>::ok() 447 // 448 // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This 449 // member function is analogous to `absl::Status::ok()` and should be used 450 // similarly to check the status of return values. 451 // 452 // Example: 453 // 454 // StatusOr<Foo> result = DoBigCalculationThatCouldFail(); 455 // if (result.ok()) { 456 // // Handle result 457 // else { 458 // // Handle error 459 // } 460 ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); } 461 462 // StatusOr<T>::status() 463 // 464 // Returns a reference to the current `absl::Status` contained within the 465 // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this 466 // function returns `absl::OkStatus()`. 467 ABSL_MUST_USE_RESULT const Status& status() const&; 468 Status status() &&; 469 470 // StatusOr<T>::value() 471 // 472 // Returns a reference to the held value if `this->ok()`. Otherwise, throws 473 // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to 474 // terminate the process if exceptions are disabled. 475 // 476 // If you have already checked the status using `this->ok()`, you probably 477 // want to use `operator*()` or `operator->()` to access the value instead of 478 // `value`. 479 // 480 // Note: for value types that are cheap to copy, prefer simple code: 481 // 482 // T value = statusor.value(); 483 // 484 // Otherwise, if the value type is expensive to copy, but can be left 485 // in the StatusOr, simply assign to a reference: 486 // 487 // T& value = statusor.value(); // or `const T&` 488 // 489 // Otherwise, if the value type supports an efficient move, it can be 490 // used as follows: 491 // 492 // T value = std::move(statusor).value(); 493 // 494 // The `std::move` on statusor instead of on the whole expression enables 495 // warnings about possible uses of the statusor object after the move. 496 const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND; 497 T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND; 498 const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND; 499 T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND; 500 501 // StatusOr<T>:: operator*() 502 // 503 // Returns a reference to the current value. 504 // 505 // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. 506 // 507 // Use `this->ok()` to verify that there is a current value within the 508 // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a 509 // similar API that guarantees crashing or throwing an exception if there is 510 // no current value. 511 const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND; 512 T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND; 513 const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND; 514 T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND; 515 516 // StatusOr<T>::operator->() 517 // 518 // Returns a pointer to the current value. 519 // 520 // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined. 521 // 522 // Use `this->ok()` to verify that there is a current value. 523 const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND; 524 T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND; 525 526 // StatusOr<T>::value_or() 527 // 528 // Returns the current value if `this->ok() == true`. Otherwise constructs a 529 // value using the provided `default_value`. 530 // 531 // Unlike `value`, this function returns by value, copying the current value 532 // if necessary. If the value type supports an efficient move, it can be used 533 // as follows: 534 // 535 // T value = std::move(statusor).value_or(def); 536 // 537 // Unlike with `value`, calling `std::move()` on the result of `value_or` will 538 // still trigger a copy. 539 template <typename U> 540 T value_or(U&& default_value) const&; 541 template <typename U> 542 T value_or(U&& default_value) &&; 543 544 // StatusOr<T>::IgnoreError() 545 // 546 // Ignores any errors. This method does nothing except potentially suppress 547 // complaints from any tools that are checking that errors are not dropped on 548 // the floor. 549 void IgnoreError() const; 550 551 // StatusOr<T>::emplace() 552 // 553 // Reconstructs the inner value T in-place using the provided args, using the 554 // T(args...) constructor. Returns reference to the reconstructed `T`. 555 template <typename... Args> 556 T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { 557 if (ok()) { 558 this->Clear(); 559 this->MakeValue(std::forward<Args>(args)...); 560 } else { 561 this->MakeValue(std::forward<Args>(args)...); 562 this->status_ = absl::OkStatus(); 563 } 564 return this->data_; 565 } 566 567 template < 568 typename U, typename... Args, 569 absl::enable_if_t< 570 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, 571 int> = 0> 572 T& emplace(std::initializer_list<U> ilist, 573 Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { 574 if (ok()) { 575 this->Clear(); 576 this->MakeValue(ilist, std::forward<Args>(args)...); 577 } else { 578 this->MakeValue(ilist, std::forward<Args>(args)...); 579 this->status_ = absl::OkStatus(); 580 } 581 return this->data_; 582 } 583 584 // StatusOr<T>::AssignStatus() 585 // 586 // Sets the status of `absl::StatusOr<T>` to the given non-ok status value. 587 // 588 // NOTE: We recommend using the constructor and `operator=` where possible. 589 // This method is intended for use in generic programming, to enable setting 590 // the status of a `StatusOr<T>` when `T` may be `Status`. In that case, the 591 // constructor and `operator=` would assign into the inner value of type 592 // `Status`, rather than status of the `StatusOr` (b/280392796). 593 // 594 // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed. 595 // In optimized builds, passing absl::OkStatus() here will have the effect 596 // of passing absl::StatusCode::kInternal as a fallback. 597 using internal_statusor::StatusOrData<T>::AssignStatus; 598 599 private: 600 using internal_statusor::StatusOrData<T>::Assign; 601 template <typename U> 602 void Assign(const absl::StatusOr<U>& other); 603 template <typename U> 604 void Assign(absl::StatusOr<U>&& other); 605 }; 606 607 // operator==() 608 // 609 // This operator checks the equality of two `absl::StatusOr<T>` objects. 610 template <typename T> 611 bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { 612 if (lhs.ok() && rhs.ok()) return *lhs == *rhs; 613 return lhs.status() == rhs.status(); 614 } 615 616 // operator!=() 617 // 618 // This operator checks the inequality of two `absl::StatusOr<T>` objects. 619 template <typename T> 620 bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) { 621 return !(lhs == rhs); 622 } 623 624 // Prints the `value` or the status in brackets to `os`. 625 // 626 // Requires `T` supports `operator<<`. Do not rely on the output format which 627 // may change without notice. 628 template <typename T, typename std::enable_if< 629 absl::HasOstreamOperator<T>::value, int>::type = 0> 630 std::ostream& operator<<(std::ostream& os, const StatusOr<T>& status_or) { 631 if (status_or.ok()) { 632 os << status_or.value(); 633 } else { 634 os << internal_statusor::StringifyRandom::OpenBrackets() 635 << status_or.status() 636 << internal_statusor::StringifyRandom::CloseBrackets(); 637 } 638 return os; 639 } 640 641 // As above, but supports `StrCat`, `StrFormat`, etc. 642 // 643 // Requires `T` has `AbslStringify`. Do not rely on the output format which 644 // may change without notice. 645 template < 646 typename Sink, typename T, 647 typename std::enable_if<absl::HasAbslStringify<T>::value, int>::type = 0> 648 void AbslStringify(Sink& sink, const StatusOr<T>& status_or) { 649 if (status_or.ok()) { 650 absl::Format(&sink, "%v", status_or.value()); 651 } else { 652 absl::Format(&sink, "%s%v%s", 653 internal_statusor::StringifyRandom::OpenBrackets(), 654 status_or.status(), 655 internal_statusor::StringifyRandom::CloseBrackets()); 656 } 657 } 658 659 //------------------------------------------------------------------------------ 660 // Implementation details for StatusOr<T> 661 //------------------------------------------------------------------------------ 662 663 // TODO(sbenza): avoid the string here completely. 664 template <typename T> 665 StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {} 666 667 template <typename T> 668 template <typename U> 669 inline void StatusOr<T>::Assign(const StatusOr<U>& other) { 670 if (other.ok()) { 671 this->Assign(*other); 672 } else { 673 this->AssignStatus(other.status()); 674 } 675 } 676 677 template <typename T> 678 template <typename U> 679 inline void StatusOr<T>::Assign(StatusOr<U>&& other) { 680 if (other.ok()) { 681 this->Assign(*std::move(other)); 682 } else { 683 this->AssignStatus(std::move(other).status()); 684 } 685 } 686 template <typename T> 687 template <typename... Args> 688 StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args) 689 : Base(absl::in_place, std::forward<Args>(args)...) {} 690 691 template <typename T> 692 template <typename U, typename... Args> 693 StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist, 694 Args&&... args) 695 : Base(absl::in_place, ilist, std::forward<Args>(args)...) {} 696 697 template <typename T> 698 const Status& StatusOr<T>::status() const& { 699 return this->status_; 700 } 701 template <typename T> 702 Status StatusOr<T>::status() && { 703 return ok() ? OkStatus() : std::move(this->status_); 704 } 705 706 template <typename T> 707 const T& StatusOr<T>::value() const& { 708 if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); 709 return this->data_; 710 } 711 712 template <typename T> 713 T& StatusOr<T>::value() & { 714 if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_); 715 return this->data_; 716 } 717 718 template <typename T> 719 const T&& StatusOr<T>::value() const&& { 720 if (!this->ok()) { 721 internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); 722 } 723 return std::move(this->data_); 724 } 725 726 template <typename T> 727 T&& StatusOr<T>::value() && { 728 if (!this->ok()) { 729 internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_)); 730 } 731 return std::move(this->data_); 732 } 733 734 template <typename T> 735 const T& StatusOr<T>::operator*() const& { 736 this->EnsureOk(); 737 return this->data_; 738 } 739 740 template <typename T> 741 T& StatusOr<T>::operator*() & { 742 this->EnsureOk(); 743 return this->data_; 744 } 745 746 template <typename T> 747 const T&& StatusOr<T>::operator*() const&& { 748 this->EnsureOk(); 749 return std::move(this->data_); 750 } 751 752 template <typename T> 753 T&& StatusOr<T>::operator*() && { 754 this->EnsureOk(); 755 return std::move(this->data_); 756 } 757 758 template <typename T> 759 absl::Nonnull<const T*> StatusOr<T>::operator->() const { 760 this->EnsureOk(); 761 return &this->data_; 762 } 763 764 template <typename T> 765 absl::Nonnull<T*> StatusOr<T>::operator->() { 766 this->EnsureOk(); 767 return &this->data_; 768 } 769 770 template <typename T> 771 template <typename U> 772 T StatusOr<T>::value_or(U&& default_value) const& { 773 if (ok()) { 774 return this->data_; 775 } 776 return std::forward<U>(default_value); 777 } 778 779 template <typename T> 780 template <typename U> 781 T StatusOr<T>::value_or(U&& default_value) && { 782 if (ok()) { 783 return std::move(this->data_); 784 } 785 return std::forward<U>(default_value); 786 } 787 788 template <typename T> 789 void StatusOr<T>::IgnoreError() const { 790 // no-op 791 } 792 793 ABSL_NAMESPACE_END 794 } // namespace absl 795 796 #endif // ABSL_STATUS_STATUSOR_H_