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