merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
58
third_party/abseil_cpp/absl/status/internal/status_internal.h
vendored
Normal file
58
third_party/abseil_cpp/absl/status/internal/status_internal.h
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2019 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
|
||||
#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/inlined_vector.h"
|
||||
#include "absl/strings/cord.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
enum class StatusCode : int;
|
||||
|
||||
namespace status_internal {
|
||||
|
||||
// Container for status payloads.
|
||||
struct Payload {
|
||||
std::string type_url;
|
||||
absl::Cord payload;
|
||||
};
|
||||
|
||||
using Payloads = absl::InlinedVector<Payload, 1>;
|
||||
|
||||
// Reference-counted representation of Status data.
|
||||
struct StatusRep {
|
||||
StatusRep(absl::StatusCode code, std::string message,
|
||||
std::unique_ptr<status_internal::Payloads> payloads)
|
||||
: ref(int32_t{1}),
|
||||
code(code),
|
||||
message(std::move(message)),
|
||||
payloads(std::move(payloads)) {}
|
||||
|
||||
std::atomic<int32_t> ref;
|
||||
absl::StatusCode code;
|
||||
std::string message;
|
||||
std::unique_ptr<status_internal::Payloads> payloads;
|
||||
};
|
||||
|
||||
absl::StatusCode MapToLocalCode(int value);
|
||||
} // namespace status_internal
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
|
||||
396
third_party/abseil_cpp/absl/status/internal/statusor_internal.h
vendored
Normal file
396
third_party/abseil_cpp/absl/status/internal/statusor_internal.h
vendored
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
// Copyright 2020 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
|
||||
#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
template <typename T>
|
||||
class ABSL_MUST_USE_RESULT StatusOr;
|
||||
|
||||
namespace internal_statusor {
|
||||
|
||||
// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
|
||||
// StatusOr<T>()`.
|
||||
template <typename T, typename U, typename = void>
|
||||
struct HasConversionOperatorToStatusOr : std::false_type {};
|
||||
|
||||
template <typename T, typename U>
|
||||
void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
|
||||
|
||||
template <typename T, typename U>
|
||||
struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
|
||||
: std::true_type {};
|
||||
|
||||
// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
|
||||
template <typename T, typename U>
|
||||
using IsConstructibleOrConvertibleFromStatusOr =
|
||||
absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
|
||||
std::is_constructible<T, const StatusOr<U>&>,
|
||||
std::is_constructible<T, StatusOr<U>&&>,
|
||||
std::is_constructible<T, const StatusOr<U>&&>,
|
||||
std::is_convertible<StatusOr<U>&, T>,
|
||||
std::is_convertible<const StatusOr<U>&, T>,
|
||||
std::is_convertible<StatusOr<U>&&, T>,
|
||||
std::is_convertible<const StatusOr<U>&&, T>>;
|
||||
|
||||
// Detects whether `T` is constructible or convertible or assignable from
|
||||
// `StatusOr<U>`.
|
||||
template <typename T, typename U>
|
||||
using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
|
||||
absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
|
||||
std::is_assignable<T&, StatusOr<U>&>,
|
||||
std::is_assignable<T&, const StatusOr<U>&>,
|
||||
std::is_assignable<T&, StatusOr<U>&&>,
|
||||
std::is_assignable<T&, const StatusOr<U>&&>>;
|
||||
|
||||
// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
|
||||
// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
|
||||
template <typename T, typename U>
|
||||
struct IsDirectInitializationAmbiguous
|
||||
: public absl::conditional_t<
|
||||
std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
|
||||
U>::value,
|
||||
std::false_type,
|
||||
IsDirectInitializationAmbiguous<
|
||||
T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
|
||||
|
||||
template <typename T, typename V>
|
||||
struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
|
||||
: public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
|
||||
|
||||
// Checks against the constraints of the direction initialization, i.e. when
|
||||
// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
|
||||
template <typename T, typename U>
|
||||
using IsDirectInitializationValid = absl::disjunction<
|
||||
// Short circuits if T is basically U.
|
||||
std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
absl::negation<absl::disjunction<
|
||||
std::is_same<absl::StatusOr<T>,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
std::is_same<absl::Status,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
std::is_same<absl::in_place_t,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
IsDirectInitializationAmbiguous<T, U>>>>;
|
||||
|
||||
// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
|
||||
// is equivalent to whether all the following conditions are met:
|
||||
// 1. `U` is `StatusOr<V>`.
|
||||
// 2. `T` is constructible and assignable from `V`.
|
||||
// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
|
||||
// For example, the following code is considered ambiguous:
|
||||
// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
|
||||
// StatusOr<bool> s1 = true; // s1.ok() && s1.ValueOrDie() == true
|
||||
// StatusOr<bool> s2 = false; // s2.ok() && s2.ValueOrDie() == false
|
||||
// s1 = s2; // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
|
||||
template <typename T, typename U>
|
||||
struct IsForwardingAssignmentAmbiguous
|
||||
: public absl::conditional_t<
|
||||
std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
|
||||
U>::value,
|
||||
std::false_type,
|
||||
IsForwardingAssignmentAmbiguous<
|
||||
T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
|
||||
: public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
|
||||
|
||||
// Checks against the constraints of the forwarding assignment, i.e. whether
|
||||
// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
|
||||
template <typename T, typename U>
|
||||
using IsForwardingAssignmentValid = absl::disjunction<
|
||||
// Short circuits if T is basically U.
|
||||
std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
absl::negation<absl::disjunction<
|
||||
std::is_same<absl::StatusOr<T>,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
std::is_same<absl::Status,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
std::is_same<absl::in_place_t,
|
||||
absl::remove_cv_t<absl::remove_reference_t<U>>>,
|
||||
IsForwardingAssignmentAmbiguous<T, U>>>>;
|
||||
|
||||
class Helper {
|
||||
public:
|
||||
// Move type-agnostic error handling to the .cc.
|
||||
static void HandleInvalidStatusCtorArg(Status*);
|
||||
ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
|
||||
};
|
||||
|
||||
// Construct an instance of T in `p` through placement new, passing Args... to
|
||||
// the constructor.
|
||||
// This abstraction is here mostly for the gcc performance fix.
|
||||
template <typename T, typename... Args>
|
||||
ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
|
||||
new (p) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Helper base class to hold the data and all operations.
|
||||
// We move all this to a base class to allow mixing with the appropriate
|
||||
// TraitsBase specialization.
|
||||
template <typename T>
|
||||
class StatusOrData {
|
||||
template <typename U>
|
||||
friend class StatusOrData;
|
||||
|
||||
public:
|
||||
StatusOrData() = delete;
|
||||
|
||||
StatusOrData(const StatusOrData& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(other.data_);
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
StatusOrData(StatusOrData&& other) noexcept {
|
||||
if (other.ok()) {
|
||||
MakeValue(std::move(other.data_));
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(std::move(other.status_));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit StatusOrData(const StatusOrData<U>& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(other.data_);
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(other.status_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit StatusOrData(StatusOrData<U>&& other) {
|
||||
if (other.ok()) {
|
||||
MakeValue(std::move(other.data_));
|
||||
MakeStatus();
|
||||
} else {
|
||||
MakeStatus(std::move(other.status_));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
explicit StatusOrData(absl::in_place_t, Args&&... args)
|
||||
: data_(std::forward<Args>(args)...) {
|
||||
MakeStatus();
|
||||
}
|
||||
|
||||
explicit StatusOrData(const T& value) : data_(value) {
|
||||
MakeStatus();
|
||||
}
|
||||
explicit StatusOrData(T&& value) : data_(std::move(value)) {
|
||||
MakeStatus();
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
|
||||
int> = 0>
|
||||
explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
StatusOrData& operator=(const StatusOrData& other) {
|
||||
if (this == &other) return *this;
|
||||
if (other.ok())
|
||||
Assign(other.data_);
|
||||
else
|
||||
AssignStatus(other.status_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StatusOrData& operator=(StatusOrData&& other) {
|
||||
if (this == &other) return *this;
|
||||
if (other.ok())
|
||||
Assign(std::move(other.data_));
|
||||
else
|
||||
AssignStatus(std::move(other.status_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
~StatusOrData() {
|
||||
if (ok()) {
|
||||
status_.~Status();
|
||||
data_.~T();
|
||||
} else {
|
||||
status_.~Status();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void Assign(U&& value) {
|
||||
if (ok()) {
|
||||
data_ = std::forward<U>(value);
|
||||
} else {
|
||||
MakeValue(std::forward<U>(value));
|
||||
status_ = OkStatus();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void AssignStatus(U&& v) {
|
||||
Clear();
|
||||
status_ = static_cast<absl::Status>(std::forward<U>(v));
|
||||
EnsureNotOk();
|
||||
}
|
||||
|
||||
bool ok() const { return status_.ok(); }
|
||||
|
||||
protected:
|
||||
// status_ will always be active after the constructor.
|
||||
// We make it a union to be able to initialize exactly how we need without
|
||||
// waste.
|
||||
// Eg. in the copy constructor we use the default constructor of Status in
|
||||
// the ok() path to avoid an extra Ref call.
|
||||
union {
|
||||
Status status_;
|
||||
};
|
||||
|
||||
// data_ is active iff status_.ok()==true
|
||||
struct Dummy {};
|
||||
union {
|
||||
// When T is const, we need some non-const object we can cast to void* for
|
||||
// the placement new. dummy_ is that object.
|
||||
Dummy dummy_;
|
||||
T data_;
|
||||
};
|
||||
|
||||
void Clear() {
|
||||
if (ok()) data_.~T();
|
||||
}
|
||||
|
||||
void EnsureOk() const {
|
||||
if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
|
||||
}
|
||||
|
||||
void EnsureNotOk() {
|
||||
if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
|
||||
}
|
||||
|
||||
// Construct the value (ie. data_) through placement new with the passed
|
||||
// argument.
|
||||
template <typename... Arg>
|
||||
void MakeValue(Arg&&... arg) {
|
||||
internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
|
||||
}
|
||||
|
||||
// Construct the status (ie. status_) through placement new with the passed
|
||||
// argument.
|
||||
template <typename... Args>
|
||||
void MakeStatus(Args&&... args) {
|
||||
internal_statusor::PlacementNew<Status>(&status_,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper base classes to allow implicitly deleted constructors and assignment
|
||||
// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
|
||||
// the copy constructor when T is not copy constructible and `StatusOr` will
|
||||
// inherit that behavior implicitly.
|
||||
template <typename T, bool = std::is_copy_constructible<T>::value>
|
||||
struct CopyCtorBase {
|
||||
CopyCtorBase() = default;
|
||||
CopyCtorBase(const CopyCtorBase&) = default;
|
||||
CopyCtorBase(CopyCtorBase&&) = default;
|
||||
CopyCtorBase& operator=(const CopyCtorBase&) = default;
|
||||
CopyCtorBase& operator=(CopyCtorBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CopyCtorBase<T, false> {
|
||||
CopyCtorBase() = default;
|
||||
CopyCtorBase(const CopyCtorBase&) = delete;
|
||||
CopyCtorBase(CopyCtorBase&&) = default;
|
||||
CopyCtorBase& operator=(const CopyCtorBase&) = default;
|
||||
CopyCtorBase& operator=(CopyCtorBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T, bool = std::is_move_constructible<T>::value>
|
||||
struct MoveCtorBase {
|
||||
MoveCtorBase() = default;
|
||||
MoveCtorBase(const MoveCtorBase&) = default;
|
||||
MoveCtorBase(MoveCtorBase&&) = default;
|
||||
MoveCtorBase& operator=(const MoveCtorBase&) = default;
|
||||
MoveCtorBase& operator=(MoveCtorBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MoveCtorBase<T, false> {
|
||||
MoveCtorBase() = default;
|
||||
MoveCtorBase(const MoveCtorBase&) = default;
|
||||
MoveCtorBase(MoveCtorBase&&) = delete;
|
||||
MoveCtorBase& operator=(const MoveCtorBase&) = default;
|
||||
MoveCtorBase& operator=(MoveCtorBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T, bool = std::is_copy_constructible<T>::value&&
|
||||
std::is_copy_assignable<T>::value>
|
||||
struct CopyAssignBase {
|
||||
CopyAssignBase() = default;
|
||||
CopyAssignBase(const CopyAssignBase&) = default;
|
||||
CopyAssignBase(CopyAssignBase&&) = default;
|
||||
CopyAssignBase& operator=(const CopyAssignBase&) = default;
|
||||
CopyAssignBase& operator=(CopyAssignBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CopyAssignBase<T, false> {
|
||||
CopyAssignBase() = default;
|
||||
CopyAssignBase(const CopyAssignBase&) = default;
|
||||
CopyAssignBase(CopyAssignBase&&) = default;
|
||||
CopyAssignBase& operator=(const CopyAssignBase&) = delete;
|
||||
CopyAssignBase& operator=(CopyAssignBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T, bool = std::is_move_constructible<T>::value&&
|
||||
std::is_move_assignable<T>::value>
|
||||
struct MoveAssignBase {
|
||||
MoveAssignBase() = default;
|
||||
MoveAssignBase(const MoveAssignBase&) = default;
|
||||
MoveAssignBase(MoveAssignBase&&) = default;
|
||||
MoveAssignBase& operator=(const MoveAssignBase&) = default;
|
||||
MoveAssignBase& operator=(MoveAssignBase&&) = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MoveAssignBase<T, false> {
|
||||
MoveAssignBase() = default;
|
||||
MoveAssignBase(const MoveAssignBase&) = default;
|
||||
MoveAssignBase(MoveAssignBase&&) = default;
|
||||
MoveAssignBase& operator=(const MoveAssignBase&) = default;
|
||||
MoveAssignBase& operator=(MoveAssignBase&&) = delete;
|
||||
};
|
||||
|
||||
ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
|
||||
|
||||
} // namespace internal_statusor
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue