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