statusor.h
Go to the documentation of this file.
00001 // Copyright (c) 2017, The Regents of the University of California
00002 // All rights reserved.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are met:
00006 // * Redistributions of source code must retain the above copyright
00007 //   notice, this list of conditions and the following disclaimer.
00008 // * Redistributions in binary form must reproduce the above copyright
00009 //   notice, this list of conditions and the following disclaimer in the
00010 //   documentation and/or other materials provided with the distribution.
00011 // * Neither the name of the University of California nor the
00012 //   names of its contributors may be used to endorse or promote products
00013 //   derived from this software without specific prior written permission.
00014 //
00015 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018 // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA
00019 // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025 // POSSIBILITY OF SUCH DAMAGE.
00026 
00027 // StatusOr<T> is the union of a Status object and a T
00028 // object. StatusOr models the concept of an object that is either a
00029 // usable value, or an error Status explaining why such a value is
00030 // not present. To this end, StatusOr<T> does not allow its Status
00031 // value to be Status::OK. Further, StatusOr<T*> does not allow the
00032 // contained pointer to be NULL.
00033 //
00034 // The primary use-case for StatusOr<T> is as the return value of a
00035 // function which may fail.
00036 //
00037 // Example client usage for a StatusOr<T>, where T is not a pointer:
00038 //
00039 //  StatusOr<float> result = DoBigCalculationThatCouldFail();
00040 //  if (result.ok()) {
00041 //    float answer = result.ValueOrDie();
00042 //    printf("Big calculation yielded: %f", answer);
00043 //  } else {
00044 //    LOG(ERROR) << result.status();
00045 //  }
00046 //
00047 // Example client usage for a StatusOr<T*>:
00048 //
00049 //  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
00050 //  if (result.ok()) {
00051 //    std::unique_ptr<Foo> foo(result.ValueOrDie());
00052 //    foo->DoSomethingCool();
00053 //  } else {
00054 //    LOG(ERROR) << result.status();
00055 //  }
00056 //
00057 // Example client usage for a StatusOr<std::unique_ptr<T>>:
00058 //
00059 //  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
00060 //  if (result.ok()) {
00061 //    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
00062 //    foo->DoSomethingCool();
00063 //  } else {
00064 //    LOG(ERROR) << result.status();
00065 //  }
00066 //
00067 // Example factory implementation returning StatusOr<T*>:
00068 //
00069 //  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
00070 //    if (arg <= 0) {
00071 //      return ::util::Status(::util::error::INVALID_ARGUMENT,
00072 //                            "Arg must be positive");
00073 //    } else {
00074 //      return new Foo(arg);
00075 //    }
00076 //  }
00077 //
00078 
00079 #ifndef UTIL_STATUSOR_H_
00080 #define UTIL_STATUSOR_H_
00081 
00082 #include <assert.h>
00083 
00084 #include <new>
00085 #include <string>
00086 #include <utility>
00087 
00088 #include "util/status.h"
00089 
00090 namespace util {
00091 
00092 template<typename T>
00093 class StatusOr {
00094   template<typename U> friend class StatusOr;
00095 
00096  public:
00097   // Construct a new StatusOr with Status::UNKNOWN status
00098   StatusOr();
00099 
00100   // Construct a new StatusOr with the given non-ok status. After calling
00101   // this constructor, calls to ValueOrDie() will CHECK-fail.
00102   //
00103   // NOTE: Not explicit - we want to use StatusOr<T> as a return
00104   // value, so it is convenient and sensible to be able to do 'return
00105   // Status()' when the return type is StatusOr<T>.
00106   //
00107   // REQUIRES: status != Status::OK. This requirement is DCHECKed.
00108   // In optimized builds, passing Status::OK here will have the effect
00109   // of passing PosixErrorSpace::EINVAL as a fallback.
00110   StatusOr(const Status& status);  // NOLINT
00111 
00112   // Construct a new StatusOr with the given value. If T is a plain pointer,
00113   // value must not be NULL. After calling this constructor, calls to
00114   // ValueOrDie() will succeed, and calls to status() will return OK.
00115   //
00116   // NOTE: Not explicit - we want to use StatusOr<T> as a return type
00117   // so it is convenient and sensible to be able to do 'return T()'
00118   // when when the return type is StatusOr<T>.
00119   //
00120   // REQUIRES: if T is a plain pointer, value != NULL. This requirement is
00121   // DCHECKed. In optimized builds, passing a NULL pointer here will have
00122   // the effect of passing PosixErrorSpace::EINVAL as a fallback.
00123   StatusOr(const T& value);  // NOLINT
00124 
00125   // Copy constructor.
00126   StatusOr(const StatusOr& other);
00127 
00128   // Conversion copy constructor, T must be copy constructible from U
00129   template<typename U>
00130   StatusOr(const StatusOr<U>& other);
00131 
00132   // Assignment operator.
00133   StatusOr& operator=(const StatusOr& other);
00134 
00135   // Conversion assignment operator, T must be assignable from U
00136   template<typename U>
00137   StatusOr& operator=(const StatusOr<U>& other);
00138 
00139   // Rvalue-reference overloads of the other constructors and assignment
00140   // operators, to support move-only types and avoid unnecessary copying.
00141   StatusOr(T&& value);  // NOLINT
00142 
00143   // Move conversion operator to avoid unecessary copy.
00144   // T must be assignable from U.
00145   // Not marked with explicit so the implicit conversion can happen.
00146   template <typename U>
00147   StatusOr(StatusOr<U>&& other);  // NOLINT
00148 
00149   // Move assignment opeartor to avoid unnecessary copy.
00150   // T must be assignable from U
00151   template <typename U>
00152   StatusOr& operator=(StatusOr<U>&& other);
00153 
00154   // Returns a reference to our status. If this contains a T, then
00155   // returns Status::OK.
00156   const Status& status() const;
00157 
00158   // Returns this->status().ok()
00159   bool ok() const;
00160 
00161   // Returns a reference to our current value, or CHECK-fails if !this->ok().
00162   // If you need to initialize a T object from the stored value,
00163   // ConsumeValueOrDie() may be more efficient.
00164   const T& ValueOrDie() const;
00165 
00166   // Returns our current value, requires this->ok(). Use this if
00167   // you would otherwise want to say std::move(s.ValueOrDie()), for example
00168   // if you need to initialize a T object from the stored value and you don't
00169   // need subsequent access to the stored value. It uses T's move constructor,
00170   // if it has one, so it will work with move-only types, and will often be
00171   // more efficient than ValueOrDie, but may leave the stored value
00172   // in an arbitrary valid state.
00173   T ConsumeValueOrDie();
00174 
00175  private:
00176   void CheckValueNotNull(const T& value);
00177 
00178   template <typename U>
00179   struct IsNull {
00180     // For non-pointer U, a reference can never be NULL.
00181     static inline bool IsValueNull(const U& t) { return false; }
00182   };
00183 
00184   template <typename U>
00185   struct IsNull<U*> {
00186     static inline bool IsValueNull(const U* t) { return t == NULL; }
00187   };
00188 
00189   Status status_;
00190   T value_;
00191 };
00192 
00194 // Implementation details for StatusOr<T>
00195 
00196 namespace internal {
00197 
00198 class StatusOrHelper {
00199  public:
00200   // Move type-agnostic error handling to the .cc.
00201   static void Crash(const util::Status& status);
00202 
00203   // Customized behavior for StatusOr<T> vs. StatusOr<T*>
00204   template<typename T>
00205   struct Specialize;
00206 };
00207 
00208 template<typename T>
00209 struct StatusOrHelper::Specialize {
00210   // For non-pointer T, a reference can never be NULL.
00211   static inline bool IsValueNull(const T& t) { return false; }
00212 };
00213 
00214 template<typename T>
00215 struct StatusOrHelper::Specialize<T*> {
00216   static inline bool IsValueNull(const T* t) { return t == NULL; }
00217 };
00218 
00219 }  // namespace internal
00220 
00221 template<typename T>
00222 inline StatusOr<T>::StatusOr()
00223     : status_(util::Status::UNKNOWN) {
00224 }
00225 
00226 template<typename T>
00227 inline StatusOr<T>::StatusOr(const Status& status) {
00228   if (status.ok()) {
00229     status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
00230   } else {
00231     status_ = status;
00232   }
00233 }
00234 
00235 template<typename T>
00236 inline StatusOr<T>::StatusOr(const T& value) {
00237   if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
00238     status_ = Status(error::INTERNAL, "NULL is not a vaild argument.");
00239   } else {
00240     status_ = Status::OK;
00241     value_ = value;
00242   }
00243 }
00244 
00245 template<typename T>
00246 inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
00247     : status_(other.status_), value_(other.value_) {
00248 }
00249 
00250 template<typename T>
00251 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
00252   status_ = other.status_;
00253   value_ = other.value_;
00254   return *this;
00255 }
00256 
00257 template<typename T>
00258 template<typename U>
00259 inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
00260     : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
00261 }
00262 
00263 template<typename T>
00264 template<typename U>
00265 inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
00266   status_ = other.status_;
00267   if (status_.ok()) value_ = other.value_;
00268   return *this;
00269 }
00270 
00271 template<typename T>
00272 inline const Status& StatusOr<T>::status() const {
00273   return status_;
00274 }
00275 
00276 template<typename T>
00277 inline bool StatusOr<T>::ok() const {
00278   return status().ok();
00279 }
00280 
00281 template<typename T>
00282 inline const T& StatusOr<T>::ValueOrDie() const {
00283   if (!status_.ok()) {
00284     internal::StatusOrHelper::Crash(status_);
00285   }
00286   return value_;
00287 }
00288 
00289 // Adpoted from tensorflow/stream_executor/lib/statusor.h
00290 
00291 template <typename T>
00292 inline StatusOr<T>::StatusOr(T&& value)
00293     : status_() {
00294   CheckValueNotNull(value);
00295   value_ = std::move(value);
00296 }
00297 
00298 template <typename T>
00299 inline T StatusOr<T>::ConsumeValueOrDie() {
00300   if (!status_.ok()) {
00301     internal::StatusOrHelper::Crash(status_);
00302   }
00303   return std::move(value_);
00304 }
00305 
00306 template <typename T>
00307 template <typename U>
00308 inline StatusOr<T>::StatusOr(StatusOr<U>&& other)  // NOLINT
00309     : status_(std::move(other.status_)),
00310       value_(std::move(other.value_)) {}
00311 
00312 // Move assignment opeartor to avoid unnecessary copy.
00313 // T must be assignable from U
00314 template <typename T>
00315 template <typename U>
00316 inline StatusOr<T>& StatusOr<T>::operator=(StatusOr<U>&& other) {
00317   status_ = std::move(other.status_);
00318   value_ = std::move(other.value_);
00319   return *this;
00320 }
00321 
00322 template <typename T>
00323 inline void StatusOr<T>::CheckValueNotNull(const T& value) {
00324   assert(!IsNull<T>::IsValueNull(value));
00325   if (IsNull<T>::IsValueNull(value)) {
00326     status_ =
00327         Status(error::INTERNAL,
00328                "NULL is not a valid constructor argument to StatusOr<T*>");
00329   }
00330 }
00331 
00332 }  // namespace util
00333 
00334 #endif  // UTIL_STATUSOR_H_
00335 
00336 
00337 // Protocol Buffers - Google's data interchange format
00338 // Copyright 2008 Google Inc.  All rights reserved.
00339 // https://developers.google.com/protocol-buffers/
00340 //
00341 // Redistribution and use in source and binary forms, with or without
00342 // modification, are permitted provided that the following conditions are
00343 // met:
00344 //
00345 //     * Redistributions of source code must retain the above copyright
00346 // notice, this list of conditions and the following disclaimer.
00347 //     * Redistributions in binary form must reproduce the above
00348 // copyright notice, this list of conditions and the following disclaimer
00349 // in the documentation and/or other materials provided with the
00350 // distribution.
00351 //     * Neither the name of Google Inc. nor the names of its
00352 // contributors may be used to endorse or promote products derived from
00353 // this software without specific prior written permission.
00354 //
00355 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00356 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00357 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00358 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00359 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00360 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00361 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00362 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00363 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00364 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00365 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00366 
00367 
00368 // Adpoted from tensorflow/stream_executor/lib/statusor.h
00369 // Copyright 2015 Google Inc. All Rights Reserved.
00370 // Licensed under the Apache License, Version 2.0 (the "License");
00371 // you may not use this file except in compliance with the License.
00372 // You may obtain a copy of the License at
00373 //     http://www.apache.org/licenses/LICENSE-2.0
00374 // Unless required by applicable law or agreed to in writing, software
00375 // distributed under the License is distributed on an "AS IS" BASIS,
00376 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00377 // See the License for the specific language governing permissions and
00378 // limitations under the License.


gcloud_speech
Author(s):
autogenerated on Thu Jun 6 2019 17:58:03