mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Bring sapi::StatusOr<>
up to date with internal Abseil changes
Note: This intentionally omits perfect-forwarding value assignments. This avoids overly complex template expressions. The regular assignments are still efficient. PiperOrigin-RevId: 304159053 Change-Id: I3460f46ca5779a0619cf90ae22625de8fad7669c
This commit is contained in:
parent
2fa0bf85f4
commit
2b2e7ac498
|
@ -19,6 +19,9 @@
|
|||
#ifndef THIRD_PARTY_SAPI_UTIL_STATUSOR_H_
|
||||
#define THIRD_PARTY_SAPI_UTIL_STATUSOR_H_
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/log_severity.h"
|
||||
|
@ -29,20 +32,15 @@
|
|||
namespace sapi {
|
||||
|
||||
template <typename T>
|
||||
class StatusOr {
|
||||
class ABSL_MUST_USE_RESULT StatusOr {
|
||||
template <typename U>
|
||||
friend class StatusOr;
|
||||
|
||||
public:
|
||||
using element_type = T;
|
||||
|
||||
explicit StatusOr() : variant_(absl::UnknownError("")) {}
|
||||
|
||||
StatusOr(const absl::Status& status) : variant_(status) { EnsureNotOk(); }
|
||||
|
||||
StatusOr& operator=(const absl::Status& status) {
|
||||
variant_ = status;
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
StatusOr(const T& value) : variant_{value} {}
|
||||
StatusOr(T&& value) : variant_{std::move(value)} {}
|
||||
|
||||
StatusOr(const StatusOr&) = default;
|
||||
StatusOr& operator=(const StatusOr&) = default;
|
||||
|
||||
|
@ -50,27 +48,84 @@ class StatusOr {
|
|||
StatusOr& operator=(StatusOr&&) = default;
|
||||
|
||||
template <typename U>
|
||||
StatusOr(const StatusOr<U>& other) {
|
||||
*this = other;
|
||||
}
|
||||
StatusOr(const StatusOr<U>& other) : StatusOr(other) {}
|
||||
|
||||
template <typename U>
|
||||
StatusOr(StatusOr<U>&& other) : StatusOr(other) {}
|
||||
|
||||
template <typename U>
|
||||
StatusOr& operator=(const StatusOr<U>& other) {
|
||||
if (other.ok()) {
|
||||
variant_ = other.ValueOrDie();
|
||||
} else {
|
||||
variant_ = other.status();
|
||||
}
|
||||
variant_ = other.ok() ? other.value() : other.status();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
StatusOr& operator=(StatusOr<U>&& other) {
|
||||
variant_ =
|
||||
other.ok() ? std::move(other).value() : std::move(other).status();
|
||||
return *this;
|
||||
}
|
||||
|
||||
StatusOr(const T& value) : variant_(value) {}
|
||||
|
||||
StatusOr(const absl::Status& status) : variant_(status) { EnsureNotOk(); }
|
||||
|
||||
// Not implemented:
|
||||
// template <typename U = T>
|
||||
// StatusOr& operator=(U&& value);
|
||||
|
||||
StatusOr(T&& value) : variant_(std::move(value)) {}
|
||||
|
||||
StatusOr(absl::Status&& value) : variant_(std::move(value)) {}
|
||||
|
||||
StatusOr& operator=(absl::Status&& status) {
|
||||
variant_ = std::move(status);
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
explicit StatusOr(absl::in_place_t, Args&&... args)
|
||||
: StatusOr(T(std::forward<Args>(args)...)) {}
|
||||
|
||||
template <typename U, typename... Args>
|
||||
explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
|
||||
Args&&... args)
|
||||
: StatusOr(ilist, U(std::forward<Args>(args)...)) {}
|
||||
|
||||
explicit operator bool() const { return ok(); }
|
||||
|
||||
ABSL_MUST_USE_RESULT bool ok() const {
|
||||
return absl::holds_alternative<T>(variant_);
|
||||
}
|
||||
|
||||
absl::Status status() const {
|
||||
return ok() ? absl::OkStatus() : absl::get<absl::Status>(variant_);
|
||||
const absl::Status& status() const& {
|
||||
static const auto* ok_status = new absl::Status();
|
||||
return ok() ? *ok_status : absl::get<absl::Status>(variant_);
|
||||
}
|
||||
|
||||
absl::Status status() && {
|
||||
return ok() ? absl::OkStatus()
|
||||
: std::move(absl::get<absl::Status>(variant_));
|
||||
}
|
||||
|
||||
const T& value() const& {
|
||||
EnsureOk();
|
||||
return absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
T& value() & {
|
||||
EnsureOk();
|
||||
return absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
const T&& value() const&& {
|
||||
EnsureOk();
|
||||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
|
||||
T&& value() && {
|
||||
EnsureOk();
|
||||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
|
||||
const T& ValueOrDie() const& {
|
||||
|
@ -88,6 +143,65 @@ class StatusOr {
|
|||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
|
||||
const T& operator*() const& {
|
||||
EnsureOk();
|
||||
return absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
T& operator*() & {
|
||||
EnsureOk();
|
||||
return absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
const T&& operator*() const&& {
|
||||
EnsureOk();
|
||||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
|
||||
T&& operator*() && {
|
||||
EnsureOk();
|
||||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
|
||||
const T* operator->() const {
|
||||
EnsureOk();
|
||||
return &absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
T* operator->() {
|
||||
EnsureOk();
|
||||
return &absl::get<T>(variant_);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
T value_or(U&& default_value) const& {
|
||||
if (ok()) {
|
||||
return absl::get<T>(variant_);
|
||||
}
|
||||
return std::forward<U>(default_value);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
T value_or(U&& default_value) && {
|
||||
if (ok()) {
|
||||
return std::move(absl::get<T>(variant_));
|
||||
}
|
||||
return std::forward<U>(default_value);
|
||||
}
|
||||
|
||||
void IgnoreError() const { /* no-op */
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
T& emplace(Args&&... args) {
|
||||
return variant_.template emplace<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename U, typename... Args>
|
||||
T& emplace(std::initializer_list<U> ilist, Args&&... args) {
|
||||
return variant_.template emplace<T>(ilist, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
void EnsureOk() const {
|
||||
if (!ok()) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
using ::testing::Eq;
|
||||
using ::testing::IsFalse;
|
||||
using ::testing::Not;
|
||||
using ::testing::Pointee;
|
||||
|
||||
namespace sapi {
|
||||
namespace {
|
||||
|
@ -366,5 +367,41 @@ TEST(StatusOrTest, ValueOrDieMovedValue) {
|
|||
EXPECT_THAT(*moved_value, Eq(kStringElement));
|
||||
}
|
||||
|
||||
TEST(StatusOrTest, MapToStatusOrUniquePtr) {
|
||||
// A reduced version of a problematic type found in the wild. All of the
|
||||
// operations below should compile.
|
||||
using MapType = std::map<std::string, StatusOr<std::unique_ptr<int>>>;
|
||||
|
||||
MapType a;
|
||||
|
||||
// Move-construction
|
||||
MapType b(std::move(a));
|
||||
|
||||
// Move-assignment
|
||||
a = std::move(b);
|
||||
}
|
||||
|
||||
TEST(StatusOrTest, ValueOrOk) {
|
||||
const StatusOr<int> status_or = 0;
|
||||
EXPECT_EQ(status_or.value_or(-1), 0);
|
||||
}
|
||||
|
||||
TEST(StatusOrTest, ValueOrDefault) {
|
||||
const StatusOr<int> status_or = absl::CancelledError();
|
||||
EXPECT_EQ(status_or.value_or(-1), -1);
|
||||
}
|
||||
|
||||
TEST(StatusOrTest, MoveOnlyValueOrOk) {
|
||||
EXPECT_THAT(StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
|
||||
.value_or(absl::make_unique<int>(-1)),
|
||||
Pointee(0));
|
||||
}
|
||||
|
||||
TEST(StatusOr, MoveOnlyValueOrDefault) {
|
||||
EXPECT_THAT(StatusOr<std::unique_ptr<int>>(absl::CancelledError())
|
||||
.value_or(absl::make_unique<int>(-1)),
|
||||
Pointee(-1));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sapi
|
||||
|
|
Loading…
Reference in New Issue
Block a user