File indexing completed on 2025-01-31 09:33:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
0015 #define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
0016
0017 #include <cstdint>
0018 #include <type_traits>
0019 #include <utility>
0020
0021 #include "absl/base/attributes.h"
0022 #include "absl/base/nullability.h"
0023 #include "absl/meta/type_traits.h"
0024 #include "absl/status/status.h"
0025 #include "absl/strings/string_view.h"
0026 #include "absl/utility/utility.h"
0027
0028 namespace absl {
0029 ABSL_NAMESPACE_BEGIN
0030
0031 template <typename T>
0032 class ABSL_MUST_USE_RESULT StatusOr;
0033
0034 namespace internal_statusor {
0035
0036
0037
0038 template <typename T, typename U, typename = void>
0039 struct HasConversionOperatorToStatusOr : std::false_type {};
0040
0041 template <typename T, typename U>
0042 void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
0043
0044 template <typename T, typename U>
0045 struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
0046 : std::true_type {};
0047
0048
0049 template <typename T, typename U>
0050 using IsConstructibleOrConvertibleFromStatusOr =
0051 absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
0052 std::is_constructible<T, const StatusOr<U>&>,
0053 std::is_constructible<T, StatusOr<U>&&>,
0054 std::is_constructible<T, const StatusOr<U>&&>,
0055 std::is_convertible<StatusOr<U>&, T>,
0056 std::is_convertible<const StatusOr<U>&, T>,
0057 std::is_convertible<StatusOr<U>&&, T>,
0058 std::is_convertible<const StatusOr<U>&&, T>>;
0059
0060
0061
0062 template <typename T, typename U>
0063 using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
0064 absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
0065 std::is_assignable<T&, StatusOr<U>&>,
0066 std::is_assignable<T&, const StatusOr<U>&>,
0067 std::is_assignable<T&, StatusOr<U>&&>,
0068 std::is_assignable<T&, const StatusOr<U>&&>>;
0069
0070
0071
0072 template <typename T, typename U>
0073 struct IsDirectInitializationAmbiguous
0074 : public absl::conditional_t<
0075 std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,
0076 IsDirectInitializationAmbiguous<T, absl::remove_cvref_t<U>>> {};
0077
0078 template <typename T, typename V>
0079 struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
0080 : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
0081
0082
0083
0084 template <typename T, typename U>
0085 using IsDirectInitializationValid = absl::disjunction<
0086
0087 std::is_same<T, absl::remove_cvref_t<U>>,
0088 absl::negation<absl::disjunction<
0089 std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,
0090 std::is_same<absl::Status, absl::remove_cvref_t<U>>,
0091 std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,
0092 IsDirectInitializationAmbiguous<T, U>>>>;
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template <typename T, typename U>
0105 struct IsForwardingAssignmentAmbiguous
0106 : public absl::conditional_t<
0107 std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,
0108 IsForwardingAssignmentAmbiguous<T, absl::remove_cvref_t<U>>> {};
0109
0110 template <typename T, typename U>
0111 struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
0112 : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
0113
0114
0115
0116 template <typename T, typename U>
0117 using IsForwardingAssignmentValid = absl::disjunction<
0118
0119 std::is_same<T, absl::remove_cvref_t<U>>,
0120 absl::negation<absl::disjunction<
0121 std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,
0122 std::is_same<absl::Status, absl::remove_cvref_t<U>>,
0123 std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,
0124 IsForwardingAssignmentAmbiguous<T, U>>>>;
0125
0126 template <bool Value, typename T>
0127 using Equality = std::conditional_t<Value, T, absl::negation<T>>;
0128
0129 template <bool Explicit, typename T, typename U, bool Lifetimebound>
0130 using IsConstructionValid = absl::conjunction<
0131 Equality<Lifetimebound,
0132 type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
0133 IsDirectInitializationValid<T, U&&>, std::is_constructible<T, U&&>,
0134 Equality<!Explicit, std::is_convertible<U&&, T>>,
0135 absl::disjunction<
0136 std::is_same<T, absl::remove_cvref_t<U>>,
0137 absl::conjunction<
0138 std::conditional_t<
0139 Explicit,
0140 absl::negation<std::is_constructible<absl::Status, U&&>>,
0141 absl::negation<std::is_convertible<U&&, absl::Status>>>,
0142 absl::negation<
0143 internal_statusor::HasConversionOperatorToStatusOr<T, U&&>>>>>;
0144
0145 template <typename T, typename U, bool Lifetimebound>
0146 using IsAssignmentValid = absl::conjunction<
0147 Equality<Lifetimebound,
0148 type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
0149 std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
0150 absl::disjunction<
0151 std::is_same<T, absl::remove_cvref_t<U>>,
0152 absl::conjunction<
0153 absl::negation<std::is_convertible<U&&, absl::Status>>,
0154 absl::negation<HasConversionOperatorToStatusOr<T, U&&>>>>,
0155 IsForwardingAssignmentValid<T, U&&>>;
0156
0157 template <bool Explicit, typename T, typename U>
0158 using IsConstructionFromStatusValid = absl::conjunction<
0159 absl::negation<std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>>,
0160 absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
0161 absl::negation<std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>>,
0162 Equality<!Explicit, std::is_convertible<U, absl::Status>>,
0163 std::is_constructible<absl::Status, U>,
0164 absl::negation<HasConversionOperatorToStatusOr<T, U>>>;
0165
0166 template <bool Explicit, typename T, typename U, bool Lifetimebound,
0167 typename UQ>
0168 using IsConstructionFromStatusOrValid = absl::conjunction<
0169 absl::negation<std::is_same<T, U>>,
0170 Equality<Lifetimebound,
0171 type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
0172 std::is_constructible<T, UQ>,
0173 Equality<!Explicit, std::is_convertible<UQ, T>>,
0174 absl::negation<IsConstructibleOrConvertibleFromStatusOr<T, U>>>;
0175
0176 template <typename T, typename U, bool Lifetimebound>
0177 using IsStatusOrAssignmentValid = absl::conjunction<
0178 absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
0179 Equality<Lifetimebound,
0180 type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
0181 std::is_constructible<T, U>, std::is_assignable<T, U>,
0182 absl::negation<IsConstructibleOrConvertibleOrAssignableFromStatusOr<
0183 T, absl::remove_cvref_t<U>>>>;
0184
0185 class Helper {
0186 public:
0187
0188 static void HandleInvalidStatusCtorArg(absl::Nonnull<Status*>);
0189 [[noreturn]] static void Crash(const absl::Status& status);
0190 };
0191
0192
0193
0194
0195 template <typename T, typename... Args>
0196 ABSL_ATTRIBUTE_NONNULL(1)
0197 void PlacementNew(absl::Nonnull<void*> p, Args&&... args) {
0198 new (p) T(std::forward<Args>(args)...);
0199 }
0200
0201
0202
0203
0204 template <typename T>
0205 class StatusOrData {
0206 template <typename U>
0207 friend class StatusOrData;
0208
0209 public:
0210 StatusOrData() = delete;
0211
0212 StatusOrData(const StatusOrData& other) {
0213 if (other.ok()) {
0214 MakeValue(other.data_);
0215 MakeStatus();
0216 } else {
0217 MakeStatus(other.status_);
0218 }
0219 }
0220
0221 StatusOrData(StatusOrData&& other) noexcept {
0222 if (other.ok()) {
0223 MakeValue(std::move(other.data_));
0224 MakeStatus();
0225 } else {
0226 MakeStatus(std::move(other.status_));
0227 }
0228 }
0229
0230 template <typename U>
0231 explicit StatusOrData(const StatusOrData<U>& other) {
0232 if (other.ok()) {
0233 MakeValue(other.data_);
0234 MakeStatus();
0235 } else {
0236 MakeStatus(other.status_);
0237 }
0238 }
0239
0240 template <typename U>
0241 explicit StatusOrData(StatusOrData<U>&& other) {
0242 if (other.ok()) {
0243 MakeValue(std::move(other.data_));
0244 MakeStatus();
0245 } else {
0246 MakeStatus(std::move(other.status_));
0247 }
0248 }
0249
0250 template <typename... Args>
0251 explicit StatusOrData(absl::in_place_t, Args&&... args)
0252 : data_(std::forward<Args>(args)...) {
0253 MakeStatus();
0254 }
0255
0256 explicit StatusOrData(const T& value) : data_(value) {
0257 MakeStatus();
0258 }
0259 explicit StatusOrData(T&& value) : data_(std::move(value)) {
0260 MakeStatus();
0261 }
0262
0263 template <typename U,
0264 absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
0265 int> = 0>
0266 explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
0267 EnsureNotOk();
0268 }
0269
0270 StatusOrData& operator=(const StatusOrData& other) {
0271 if (this == &other) return *this;
0272 if (other.ok())
0273 Assign(other.data_);
0274 else
0275 AssignStatus(other.status_);
0276 return *this;
0277 }
0278
0279 StatusOrData& operator=(StatusOrData&& other) {
0280 if (this == &other) return *this;
0281 if (other.ok())
0282 Assign(std::move(other.data_));
0283 else
0284 AssignStatus(std::move(other.status_));
0285 return *this;
0286 }
0287
0288 ~StatusOrData() {
0289 if (ok()) {
0290 status_.~Status();
0291 data_.~T();
0292 } else {
0293 status_.~Status();
0294 }
0295 }
0296
0297 template <typename U>
0298 void Assign(U&& value) {
0299 if (ok()) {
0300 data_ = std::forward<U>(value);
0301 } else {
0302 MakeValue(std::forward<U>(value));
0303 status_ = OkStatus();
0304 }
0305 }
0306
0307 template <typename U>
0308 void AssignStatus(U&& v) {
0309 Clear();
0310 status_ = static_cast<absl::Status>(std::forward<U>(v));
0311 EnsureNotOk();
0312 }
0313
0314 bool ok() const { return status_.ok(); }
0315
0316 protected:
0317
0318
0319
0320
0321
0322 union {
0323 Status status_;
0324 };
0325
0326
0327 struct Dummy {};
0328 union {
0329
0330
0331 Dummy dummy_;
0332 T data_;
0333 };
0334
0335 void Clear() {
0336 if (ok()) data_.~T();
0337 }
0338
0339 void EnsureOk() const {
0340 if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
0341 }
0342
0343 void EnsureNotOk() {
0344 if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
0345 }
0346
0347
0348
0349 template <typename... Arg>
0350 void MakeValue(Arg&&... arg) {
0351 internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
0352 }
0353
0354
0355
0356 template <typename... Args>
0357 void MakeStatus(Args&&... args) {
0358 internal_statusor::PlacementNew<Status>(&status_,
0359 std::forward<Args>(args)...);
0360 }
0361 };
0362
0363
0364
0365
0366
0367 template <typename T, bool = std::is_copy_constructible<T>::value>
0368 struct CopyCtorBase {
0369 CopyCtorBase() = default;
0370 CopyCtorBase(const CopyCtorBase&) = default;
0371 CopyCtorBase(CopyCtorBase&&) = default;
0372 CopyCtorBase& operator=(const CopyCtorBase&) = default;
0373 CopyCtorBase& operator=(CopyCtorBase&&) = default;
0374 };
0375
0376 template <typename T>
0377 struct CopyCtorBase<T, false> {
0378 CopyCtorBase() = default;
0379 CopyCtorBase(const CopyCtorBase&) = delete;
0380 CopyCtorBase(CopyCtorBase&&) = default;
0381 CopyCtorBase& operator=(const CopyCtorBase&) = default;
0382 CopyCtorBase& operator=(CopyCtorBase&&) = default;
0383 };
0384
0385 template <typename T, bool = std::is_move_constructible<T>::value>
0386 struct MoveCtorBase {
0387 MoveCtorBase() = default;
0388 MoveCtorBase(const MoveCtorBase&) = default;
0389 MoveCtorBase(MoveCtorBase&&) = default;
0390 MoveCtorBase& operator=(const MoveCtorBase&) = default;
0391 MoveCtorBase& operator=(MoveCtorBase&&) = default;
0392 };
0393
0394 template <typename T>
0395 struct MoveCtorBase<T, false> {
0396 MoveCtorBase() = default;
0397 MoveCtorBase(const MoveCtorBase&) = default;
0398 MoveCtorBase(MoveCtorBase&&) = delete;
0399 MoveCtorBase& operator=(const MoveCtorBase&) = default;
0400 MoveCtorBase& operator=(MoveCtorBase&&) = default;
0401 };
0402
0403 template <typename T, bool = std::is_copy_constructible<T>::value&&
0404 std::is_copy_assignable<T>::value>
0405 struct CopyAssignBase {
0406 CopyAssignBase() = default;
0407 CopyAssignBase(const CopyAssignBase&) = default;
0408 CopyAssignBase(CopyAssignBase&&) = default;
0409 CopyAssignBase& operator=(const CopyAssignBase&) = default;
0410 CopyAssignBase& operator=(CopyAssignBase&&) = default;
0411 };
0412
0413 template <typename T>
0414 struct CopyAssignBase<T, false> {
0415 CopyAssignBase() = default;
0416 CopyAssignBase(const CopyAssignBase&) = default;
0417 CopyAssignBase(CopyAssignBase&&) = default;
0418 CopyAssignBase& operator=(const CopyAssignBase&) = delete;
0419 CopyAssignBase& operator=(CopyAssignBase&&) = default;
0420 };
0421
0422 template <typename T, bool = std::is_move_constructible<T>::value&&
0423 std::is_move_assignable<T>::value>
0424 struct MoveAssignBase {
0425 MoveAssignBase() = default;
0426 MoveAssignBase(const MoveAssignBase&) = default;
0427 MoveAssignBase(MoveAssignBase&&) = default;
0428 MoveAssignBase& operator=(const MoveAssignBase&) = default;
0429 MoveAssignBase& operator=(MoveAssignBase&&) = default;
0430 };
0431
0432 template <typename T>
0433 struct MoveAssignBase<T, false> {
0434 MoveAssignBase() = default;
0435 MoveAssignBase(const MoveAssignBase&) = default;
0436 MoveAssignBase(MoveAssignBase&&) = default;
0437 MoveAssignBase& operator=(const MoveAssignBase&) = default;
0438 MoveAssignBase& operator=(MoveAssignBase&&) = delete;
0439 };
0440
0441 [[noreturn]] void ThrowBadStatusOrAccess(absl::Status status);
0442
0443
0444
0445 class StringifyRandom {
0446 enum BracesType {
0447 kBareParens = 0,
0448 kSpaceParens,
0449 kBareBrackets,
0450 kSpaceBrackets,
0451 };
0452
0453
0454 static BracesType RandomBraces() {
0455 static const BracesType kRandomBraces = static_cast<BracesType>(
0456 (reinterpret_cast<uintptr_t>(&kRandomBraces) >> 4) % 4);
0457 return kRandomBraces;
0458 }
0459
0460 public:
0461 static inline absl::string_view OpenBrackets() {
0462 switch (RandomBraces()) {
0463 case kBareParens:
0464 return "(";
0465 case kSpaceParens:
0466 return "( ";
0467 case kBareBrackets:
0468 return "[";
0469 case kSpaceBrackets:
0470 return "[ ";
0471 }
0472 return "(";
0473 }
0474
0475 static inline absl::string_view CloseBrackets() {
0476 switch (RandomBraces()) {
0477 case kBareParens:
0478 return ")";
0479 case kSpaceParens:
0480 return " )";
0481 case kBareBrackets:
0482 return "]";
0483 case kSpaceBrackets:
0484 return " ]";
0485 }
0486 return ")";
0487 }
0488 };
0489
0490 }
0491 ABSL_NAMESPACE_END
0492 }
0493
0494 #endif