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_cvref_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_cvref_t<U>, T>,
448 absl::conjunction<
449 absl::negation<std::is_convertible<U&&, absl::Status>>,
450 absl::negation<
451 internal_statusor::HasConversionOperatorToStatusOr<
452 T, U&&>>>>>::value,
453 int> = 0>
StatusOr(U && u)454 StatusOr(U&& u) // NOLINT
455 : StatusOr(absl::in_place, std::forward<U>(u)) {}
456
457 template <
458 typename U = T,
459 absl::enable_if_t<
460 absl::conjunction<
461 internal_statusor::IsDirectInitializationValid<T, U&&>,
462 absl::disjunction<
463 std::is_same<absl::remove_cvref_t<U>, T>,
464 absl::conjunction<
465 absl::negation<std::is_constructible<absl::Status, U&&>>,
466 absl::negation<
467 internal_statusor::HasConversionOperatorToStatusOr<
468 T, U&&>>>>,
469 std::is_constructible<T, U&&>,
470 absl::negation<std::is_convertible<U&&, T>>>::value,
471 int> = 0>
StatusOr(U && u)472 explicit StatusOr(U&& u) // NOLINT
473 : StatusOr(absl::in_place, std::forward<U>(u)) {}
474
475 // StatusOr<T>::ok()
476 //
477 // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
478 // member function is analogous to `absl::Status::ok()` and should be used
479 // similarly to check the status of return values.
480 //
481 // Example:
482 //
483 // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
484 // if (result.ok()) {
485 // // Handle result
486 // else {
487 // // Handle error
488 // }
ok()489 ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
490
491 // StatusOr<T>::status()
492 //
493 // Returns a reference to the current `absl::Status` contained within the
494 // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
495 // function returns `absl::OkStatus()`.
496 const Status& status() const&;
497 Status status() &&;
498
499 // StatusOr<T>::value()
500 //
501 // Returns a reference to the held value if `this->ok()`. Otherwise, throws
502 // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
503 // terminate the process if exceptions are disabled.
504 //
505 // If you have already checked the status using `this->ok()`, you probably
506 // want to use `operator*()` or `operator->()` to access the value instead of
507 // `value`.
508 //
509 // Note: for value types that are cheap to copy, prefer simple code:
510 //
511 // T value = statusor.value();
512 //
513 // Otherwise, if the value type is expensive to copy, but can be left
514 // in the StatusOr, simply assign to a reference:
515 //
516 // T& value = statusor.value(); // or `const T&`
517 //
518 // Otherwise, if the value type supports an efficient move, it can be
519 // used as follows:
520 //
521 // T value = std::move(statusor).value();
522 //
523 // The `std::move` on statusor instead of on the whole expression enables
524 // warnings about possible uses of the statusor object after the move.
525 const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
526 T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
527 const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
528 T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
529
530 // StatusOr<T>:: operator*()
531 //
532 // Returns a reference to the current value.
533 //
534 // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
535 //
536 // Use `this->ok()` to verify that there is a current value within the
537 // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
538 // similar API that guarantees crashing or throwing an exception if there is
539 // no current value.
540 const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
541 T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
542 const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
543 T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
544
545 // StatusOr<T>::operator->()
546 //
547 // Returns a pointer to the current value.
548 //
549 // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
550 //
551 // Use `this->ok()` to verify that there is a current value.
552 const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
553 T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND;
554
555 // StatusOr<T>::value_or()
556 //
557 // Returns the current value if `this->ok() == true`. Otherwise constructs a
558 // value using the provided `default_value`.
559 //
560 // Unlike `value`, this function returns by value, copying the current value
561 // if necessary. If the value type supports an efficient move, it can be used
562 // as follows:
563 //
564 // T value = std::move(statusor).value_or(def);
565 //
566 // Unlike with `value`, calling `std::move()` on the result of `value_or` will
567 // still trigger a copy.
568 template <typename U>
569 T value_or(U&& default_value) const&;
570 template <typename U>
571 T value_or(U&& default_value) &&;
572
573 // StatusOr<T>::IgnoreError()
574 //
575 // Ignores any errors. This method does nothing except potentially suppress
576 // complaints from any tools that are checking that errors are not dropped on
577 // the floor.
578 void IgnoreError() const;
579
580 // StatusOr<T>::emplace()
581 //
582 // Reconstructs the inner value T in-place using the provided args, using the
583 // T(args...) constructor. Returns reference to the reconstructed `T`.
584 template <typename... Args>
emplace(Args &&...args)585 T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
586 if (ok()) {
587 this->Clear();
588 this->MakeValue(std::forward<Args>(args)...);
589 } else {
590 this->MakeValue(std::forward<Args>(args)...);
591 this->status_ = absl::OkStatus();
592 }
593 return this->data_;
594 }
595
596 template <
597 typename U, typename... Args,
598 absl::enable_if_t<
599 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
600 int> = 0>
emplace(std::initializer_list<U> ilist,Args &&...args)601 T& emplace(std::initializer_list<U> ilist,
602 Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
603 if (ok()) {
604 this->Clear();
605 this->MakeValue(ilist, std::forward<Args>(args)...);
606 } else {
607 this->MakeValue(ilist, std::forward<Args>(args)...);
608 this->status_ = absl::OkStatus();
609 }
610 return this->data_;
611 }
612
613 // StatusOr<T>::AssignStatus()
614 //
615 // Sets the status of `absl::StatusOr<T>` to the given non-ok status value.
616 //
617 // NOTE: We recommend using the constructor and `operator=` where possible.
618 // This method is intended for use in generic programming, to enable setting
619 // the status of a `StatusOr<T>` when `T` may be `Status`. In that case, the
620 // constructor and `operator=` would assign into the inner value of type
621 // `Status`, rather than status of the `StatusOr` (b/280392796).
622 //
623 // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
624 // In optimized builds, passing absl::OkStatus() here will have the effect
625 // of passing absl::StatusCode::kInternal as a fallback.
626 using internal_statusor::StatusOrData<T>::AssignStatus;
627
628 private:
629 using internal_statusor::StatusOrData<T>::Assign;
630 template <typename U>
631 void Assign(const absl::StatusOr<U>& other);
632 template <typename U>
633 void Assign(absl::StatusOr<U>&& other);
634 };
635
636 // operator==()
637 //
638 // This operator checks the equality of two `absl::StatusOr<T>` objects.
639 template <typename T>
640 bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
641 if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
642 return lhs.status() == rhs.status();
643 }
644
645 // operator!=()
646 //
647 // This operator checks the inequality of two `absl::StatusOr<T>` objects.
648 template <typename T>
649 bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
650 return !(lhs == rhs);
651 }
652
653 //------------------------------------------------------------------------------
654 // Implementation details for StatusOr<T>
655 //------------------------------------------------------------------------------
656
657 // TODO(sbenza): avoid the string here completely.
658 template <typename T>
StatusOr()659 StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
660
661 template <typename T>
662 template <typename U>
Assign(const StatusOr<U> & other)663 inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
664 if (other.ok()) {
665 this->Assign(*other);
666 } else {
667 this->AssignStatus(other.status());
668 }
669 }
670
671 template <typename T>
672 template <typename U>
Assign(StatusOr<U> && other)673 inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
674 if (other.ok()) {
675 this->Assign(*std::move(other));
676 } else {
677 this->AssignStatus(std::move(other).status());
678 }
679 }
680 template <typename T>
681 template <typename... Args>
StatusOr(absl::in_place_t,Args &&...args)682 StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
683 : Base(absl::in_place, std::forward<Args>(args)...) {}
684
685 template <typename T>
686 template <typename U, typename... Args>
StatusOr(absl::in_place_t,std::initializer_list<U> ilist,Args &&...args)687 StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
688 Args&&... args)
689 : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
690
691 template <typename T>
status()692 const Status& StatusOr<T>::status() const& {
693 return this->status_;
694 }
695 template <typename T>
status()696 Status StatusOr<T>::status() && {
697 return ok() ? OkStatus() : std::move(this->status_);
698 }
699
700 template <typename T>
value()701 const T& StatusOr<T>::value() const& {
702 if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
703 return this->data_;
704 }
705
706 template <typename T>
value()707 T& StatusOr<T>::value() & {
708 if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
709 return this->data_;
710 }
711
712 template <typename T>
value()713 const T&& StatusOr<T>::value() const&& {
714 if (!this->ok()) {
715 internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
716 }
717 return std::move(this->data_);
718 }
719
720 template <typename T>
value()721 T&& StatusOr<T>::value() && {
722 if (!this->ok()) {
723 internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
724 }
725 return std::move(this->data_);
726 }
727
728 template <typename T>
729 const T& StatusOr<T>::operator*() const& {
730 this->EnsureOk();
731 return this->data_;
732 }
733
734 template <typename T>
735 T& StatusOr<T>::operator*() & {
736 this->EnsureOk();
737 return this->data_;
738 }
739
740 template <typename T>
741 const T&& StatusOr<T>::operator*() const&& {
742 this->EnsureOk();
743 return std::move(this->data_);
744 }
745
746 template <typename T>
747 T&& StatusOr<T>::operator*() && {
748 this->EnsureOk();
749 return std::move(this->data_);
750 }
751
752 template <typename T>
753 const T* StatusOr<T>::operator->() const {
754 this->EnsureOk();
755 return &this->data_;
756 }
757
758 template <typename T>
759 T* StatusOr<T>::operator->() {
760 this->EnsureOk();
761 return &this->data_;
762 }
763
764 template <typename T>
765 template <typename U>
value_or(U && default_value)766 T StatusOr<T>::value_or(U&& default_value) const& {
767 if (ok()) {
768 return this->data_;
769 }
770 return std::forward<U>(default_value);
771 }
772
773 template <typename T>
774 template <typename U>
value_or(U && default_value)775 T StatusOr<T>::value_or(U&& default_value) && {
776 if (ok()) {
777 return std::move(this->data_);
778 }
779 return std::forward<U>(default_value);
780 }
781
782 template <typename T>
IgnoreError()783 void StatusOr<T>::IgnoreError() const {
784 // no-op
785 }
786
787 ABSL_NAMESPACE_END
788 } // namespace absl
789
790 #endif // ABSL_STATUS_STATUSOR_H_
791