statusor.h
Go to the documentation of this file.
1 // Copyright (c) 2017, The Regents of the University of California
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name of the University of California nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA
19 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 // POSSIBILITY OF SUCH DAMAGE.
26 
27 // StatusOr<T> is the union of a Status object and a T
28 // object. StatusOr models the concept of an object that is either a
29 // usable value, or an error Status explaining why such a value is
30 // not present. To this end, StatusOr<T> does not allow its Status
31 // value to be Status::OK. Further, StatusOr<T*> does not allow the
32 // contained pointer to be NULL.
33 //
34 // The primary use-case for StatusOr<T> is as the return value of a
35 // function which may fail.
36 //
37 // Example client usage for a StatusOr<T>, where T is not a pointer:
38 //
39 // StatusOr<float> result = DoBigCalculationThatCouldFail();
40 // if (result.ok()) {
41 // float answer = result.ValueOrDie();
42 // printf("Big calculation yielded: %f", answer);
43 // } else {
44 // LOG(ERROR) << result.status();
45 // }
46 //
47 // Example client usage for a StatusOr<T*>:
48 //
49 // StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
50 // if (result.ok()) {
51 // std::unique_ptr<Foo> foo(result.ValueOrDie());
52 // foo->DoSomethingCool();
53 // } else {
54 // LOG(ERROR) << result.status();
55 // }
56 //
57 // Example client usage for a StatusOr<std::unique_ptr<T>>:
58 //
59 // StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
60 // if (result.ok()) {
61 // std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
62 // foo->DoSomethingCool();
63 // } else {
64 // LOG(ERROR) << result.status();
65 // }
66 //
67 // Example factory implementation returning StatusOr<T*>:
68 //
69 // StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
70 // if (arg <= 0) {
71 // return ::util::Status(::util::error::INVALID_ARGUMENT,
72 // "Arg must be positive");
73 // } else {
74 // return new Foo(arg);
75 // }
76 // }
77 //
78 
79 #ifndef UTIL_STATUSOR_H_
80 #define UTIL_STATUSOR_H_
81 
82 #include <assert.h>
83 
84 #include <new>
85 #include <string>
86 #include <utility>
87 
88 #include "util/status.h"
89 
90 namespace util {
91 
92 template<typename T>
93 class StatusOr {
94  template<typename U> friend class StatusOr;
95 
96  public:
97  // Construct a new StatusOr with Status::UNKNOWN status
98  StatusOr();
99 
100  // Construct a new StatusOr with the given non-ok status. After calling
101  // this constructor, calls to ValueOrDie() will CHECK-fail.
102  //
103  // NOTE: Not explicit - we want to use StatusOr<T> as a return
104  // value, so it is convenient and sensible to be able to do 'return
105  // Status()' when the return type is StatusOr<T>.
106  //
107  // REQUIRES: status != Status::OK. This requirement is DCHECKed.
108  // In optimized builds, passing Status::OK here will have the effect
109  // of passing PosixErrorSpace::EINVAL as a fallback.
110  StatusOr(const Status& status); // NOLINT
111 
112  // Construct a new StatusOr with the given value. If T is a plain pointer,
113  // value must not be NULL. After calling this constructor, calls to
114  // ValueOrDie() will succeed, and calls to status() will return OK.
115  //
116  // NOTE: Not explicit - we want to use StatusOr<T> as a return type
117  // so it is convenient and sensible to be able to do 'return T()'
118  // when when the return type is StatusOr<T>.
119  //
120  // REQUIRES: if T is a plain pointer, value != NULL. This requirement is
121  // DCHECKed. In optimized builds, passing a NULL pointer here will have
122  // the effect of passing PosixErrorSpace::EINVAL as a fallback.
123  StatusOr(const T& value); // NOLINT
124 
125  // Copy constructor.
126  StatusOr(const StatusOr& other);
127 
128  // Conversion copy constructor, T must be copy constructible from U
129  template<typename U>
130  StatusOr(const StatusOr<U>& other);
131 
132  // Assignment operator.
133  StatusOr& operator=(const StatusOr& other);
134 
135  // Conversion assignment operator, T must be assignable from U
136  template<typename U>
137  StatusOr& operator=(const StatusOr<U>& other);
138 
139  // Rvalue-reference overloads of the other constructors and assignment
140  // operators, to support move-only types and avoid unnecessary copying.
141  StatusOr(T&& value); // NOLINT
142 
143  // Move conversion operator to avoid unecessary copy.
144  // T must be assignable from U.
145  // Not marked with explicit so the implicit conversion can happen.
146  template <typename U>
147  StatusOr(StatusOr<U>&& other); // NOLINT
148 
149  // Move assignment opeartor to avoid unnecessary copy.
150  // T must be assignable from U
151  template <typename U>
152  StatusOr& operator=(StatusOr<U>&& other);
153 
154  // Returns a reference to our status. If this contains a T, then
155  // returns Status::OK.
156  const Status& status() const;
157 
158  // Returns this->status().ok()
159  bool ok() const;
160 
161  // Returns a reference to our current value, or CHECK-fails if !this->ok().
162  // If you need to initialize a T object from the stored value,
163  // ConsumeValueOrDie() may be more efficient.
164  const T& ValueOrDie() const;
165 
166  // Returns our current value, requires this->ok(). Use this if
167  // you would otherwise want to say std::move(s.ValueOrDie()), for example
168  // if you need to initialize a T object from the stored value and you don't
169  // need subsequent access to the stored value. It uses T's move constructor,
170  // if it has one, so it will work with move-only types, and will often be
171  // more efficient than ValueOrDie, but may leave the stored value
172  // in an arbitrary valid state.
173  T ConsumeValueOrDie();
174 
175  private:
176  void CheckValueNotNull(const T& value);
177 
178  template <typename U>
179  struct IsNull {
180  // For non-pointer U, a reference can never be NULL.
181  static inline bool IsValueNull(const U& t) { return false; }
182  };
183 
184  template <typename U>
185  struct IsNull<U*> {
186  static inline bool IsValueNull(const U* t) { return t == NULL; }
187  };
188 
191 };
192 
194 // Implementation details for StatusOr<T>
195 
196 namespace internal {
197 
199  public:
200  // Move type-agnostic error handling to the .cc.
201  static void Crash(const util::Status& status);
202 
203  // Customized behavior for StatusOr<T> vs. StatusOr<T*>
204  template<typename T>
205  struct Specialize;
206 };
207 
208 template<typename T>
210  // For non-pointer T, a reference can never be NULL.
211  static inline bool IsValueNull(const T& t) { return false; }
212 };
213 
214 template<typename T>
216  static inline bool IsValueNull(const T* t) { return t == NULL; }
217 };
218 
219 } // namespace internal
220 
221 template<typename T>
223  : status_(util::Status::UNKNOWN) {
224 }
225 
226 template<typename T>
228  if (status.ok()) {
229  status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
230  } else {
231  status_ = status;
232  }
233 }
234 
235 template<typename T>
236 inline StatusOr<T>::StatusOr(const T& value) {
238  status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
239  } else {
241  value_ = value;
242  }
243 }
244 
245 template<typename T>
246 inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
247  : status_(other.status_), value_(other.value_) {
248 }
249 
250 template<typename T>
252  status_ = other.status_;
253  value_ = other.value_;
254  return *this;
255 }
256 
257 template<typename T>
258 template<typename U>
259 inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
260  : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
261 }
262 
263 template<typename T>
264 template<typename U>
266  status_ = other.status_;
267  if (status_.ok()) value_ = other.value_;
268  return *this;
269 }
270 
271 template<typename T>
272 inline const Status& StatusOr<T>::status() const {
273  return status_;
274 }
275 
276 template<typename T>
277 inline bool StatusOr<T>::ok() const {
278  return status().ok();
279 }
280 
281 template<typename T>
282 inline const T& StatusOr<T>::ValueOrDie() const {
283  if (!status_.ok()) {
285  }
286  return value_;
287 }
288 
289 // Adpoted from tensorflow/stream_executor/lib/statusor.h
290 
291 template <typename T>
292 inline StatusOr<T>::StatusOr(T&& value)
293  : status_() {
294  CheckValueNotNull(value);
295  value_ = std::move(value);
296 }
297 
298 template <typename T>
300  if (!status_.ok()) {
302  }
303  return std::move(value_);
304 }
305 
306 template <typename T>
307 template <typename U>
308 inline StatusOr<T>::StatusOr(StatusOr<U>&& other) // NOLINT
309  : status_(std::move(other.status_)),
310  value_(std::move(other.value_)) {}
311 
312 // Move assignment opeartor to avoid unnecessary copy.
313 // T must be assignable from U
314 template <typename T>
315 template <typename U>
317  status_ = std::move(other.status_);
318  value_ = std::move(other.value_);
319  return *this;
320 }
321 
322 template <typename T>
323 inline void StatusOr<T>::CheckValueNotNull(const T& value) {
324  assert(!IsNull<T>::IsValueNull(value));
325  if (IsNull<T>::IsValueNull(value)) {
326  status_ =
328  "NULL is not a valid constructor argument to StatusOr<T*>");
329  }
330 }
331 
332 } // namespace util
333 
334 #endif // UTIL_STATUSOR_H_
335 
336 
337 // Protocol Buffers - Google's data interchange format
338 // Copyright 2008 Google Inc. All rights reserved.
339 // https://developers.google.com/protocol-buffers/
340 //
341 // Redistribution and use in source and binary forms, with or without
342 // modification, are permitted provided that the following conditions are
343 // met:
344 //
345 // * Redistributions of source code must retain the above copyright
346 // notice, this list of conditions and the following disclaimer.
347 // * Redistributions in binary form must reproduce the above
348 // copyright notice, this list of conditions and the following disclaimer
349 // in the documentation and/or other materials provided with the
350 // distribution.
351 // * Neither the name of Google Inc. nor the names of its
352 // contributors may be used to endorse or promote products derived from
353 // this software without specific prior written permission.
354 //
355 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
356 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
357 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
358 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
359 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
360 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
361 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
364 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
365 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
366 
367 
368 // Adpoted from tensorflow/stream_executor/lib/statusor.h
369 // Copyright 2015 Google Inc. All Rights Reserved.
370 // Licensed under the Apache License, Version 2.0 (the "License");
371 // you may not use this file except in compliance with the License.
372 // You may obtain a copy of the License at
373 // http://www.apache.org/licenses/LICENSE-2.0
374 // Unless required by applicable law or agreed to in writing, software
375 // distributed under the License is distributed on an "AS IS" BASIS,
376 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
377 // See the License for the specific language governing permissions and
378 // limitations under the License.
static const Status OK
Definition: status.h:74
T ConsumeValueOrDie()
Definition: statusor.h:299
bool ok() const
Definition: status.h:79
void CheckValueNotNull(const T &value)
Definition: statusor.h:323
static void Crash(const util::Status &status)
Definition: statusor.cc:34
bool ok() const
Definition: statusor.h:277
Status status_
Definition: statusor.h:189
StatusOr & operator=(const StatusOr &other)
Definition: statusor.h:251
const Status & status() const
Definition: statusor.h:272
static bool IsValueNull(const T &t)
Definition: statusor.h:211
const T & ValueOrDie() const
Definition: statusor.h:282
static bool IsValueNull(const U *t)
Definition: statusor.h:186
static bool IsValueNull(const U &t)
Definition: statusor.h:181


gcloud_speech
Author(s):
autogenerated on Mon Jun 10 2019 13:20:53