abseil-cpp/absl/status/internal/statusor_internal.h
Go to the documentation of this file.
1 // Copyright 2020 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
15 #define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
16 
17 #include <type_traits>
18 #include <utility>
19 
20 #include "absl/base/attributes.h"
21 #include "absl/meta/type_traits.h"
22 #include "absl/status/status.h"
23 #include "absl/utility/utility.h"
24 
25 namespace absl {
27 
28 template <typename T>
30 
31 namespace internal_statusor {
32 
33 // Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
34 // StatusOr<T>()`.
35 template <typename T, typename U, typename = void>
37 
38 template <typename T, typename U>
39 void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
40 
41 template <typename T, typename U>
42 struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
43  : std::true_type {};
44 
45 // Detects whether `T` is constructible or convertible from `StatusOr<U>`.
46 template <typename T, typename U>
49  std::is_constructible<T, const StatusOr<U>&>,
50  std::is_constructible<T, StatusOr<U>&&>,
51  std::is_constructible<T, const StatusOr<U>&&>,
52  std::is_convertible<StatusOr<U>&, T>,
53  std::is_convertible<const StatusOr<U>&, T>,
54  std::is_convertible<StatusOr<U>&&, T>,
55  std::is_convertible<const StatusOr<U>&&, T>>;
56 
57 // Detects whether `T` is constructible or convertible or assignable from
58 // `StatusOr<U>`.
59 template <typename T, typename U>
62  std::is_assignable<T&, StatusOr<U>&>,
63  std::is_assignable<T&, const StatusOr<U>&>,
64  std::is_assignable<T&, StatusOr<U>&&>,
65  std::is_assignable<T&, const StatusOr<U>&&>>;
66 
67 // Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
68 // when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
69 template <typename T, typename U>
71  : public absl::conditional_t<
72  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
73  U>::value,
74  std::false_type,
75  IsDirectInitializationAmbiguous<
76  T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
77 
78 template <typename T, typename V>
81 
82 // Checks against the constraints of the direction initialization, i.e. when
83 // `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
84 template <typename T, typename U>
86  // Short circuits if T is basically U.
87  std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
89  std::is_same<absl::StatusOr<T>,
91  std::is_same<absl::Status,
93  std::is_same<absl::in_place_t,
96 
97 // This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
98 // is equivalent to whether all the following conditions are met:
99 // 1. `U` is `StatusOr<V>`.
100 // 2. `T` is constructible and assignable from `V`.
101 // 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
102 // For example, the following code is considered ambiguous:
103 // (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
104 // StatusOr<bool> s1 = true; // s1.ok() && s1.ValueOrDie() == true
105 // StatusOr<bool> s2 = false; // s2.ok() && s2.ValueOrDie() == false
106 // s1 = s2; // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
107 template <typename T, typename U>
109  : public absl::conditional_t<
110  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
111  U>::value,
112  std::false_type,
113  IsForwardingAssignmentAmbiguous<
114  T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
115 
116 template <typename T, typename U>
119 
120 // Checks against the constraints of the forwarding assignment, i.e. whether
121 // `StatusOr<T>::operator(U&&)` should participate in overload resolution.
122 template <typename T, typename U>
124  // Short circuits if T is basically U.
125  std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
127  std::is_same<absl::StatusOr<T>,
129  std::is_same<absl::Status,
131  std::is_same<absl::in_place_t,
134 
135 class Helper {
136  public:
137  // Move type-agnostic error handling to the .cc.
138  static void HandleInvalidStatusCtorArg(Status*);
139  ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
140 };
141 
142 // Construct an instance of T in `p` through placement new, passing Args... to
143 // the constructor.
144 // This abstraction is here mostly for the gcc performance fix.
145 template <typename T, typename... Args>
146 ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
147  new (p) T(std::forward<Args>(args)...);
148 }
149 
150 // Helper base class to hold the data and all operations.
151 // We move all this to a base class to allow mixing with the appropriate
152 // TraitsBase specialization.
153 template <typename T>
155  template <typename U>
156  friend class StatusOrData;
157 
158  public:
159  StatusOrData() = delete;
160 
161  StatusOrData(const StatusOrData& other) {
162  if (other.ok()) {
163  MakeValue(other.data_);
164  MakeStatus();
165  } else {
166  MakeStatus(other.status_);
167  }
168  }
169 
170  StatusOrData(StatusOrData&& other) noexcept {
171  if (other.ok()) {
172  MakeValue(std::move(other.data_));
173  MakeStatus();
174  } else {
175  MakeStatus(std::move(other.status_));
176  }
177  }
178 
179  template <typename U>
180  explicit StatusOrData(const StatusOrData<U>& other) {
181  if (other.ok()) {
182  MakeValue(other.data_);
183  MakeStatus();
184  } else {
185  MakeStatus(other.status_);
186  }
187  }
188 
189  template <typename U>
190  explicit StatusOrData(StatusOrData<U>&& other) {
191  if (other.ok()) {
192  MakeValue(std::move(other.data_));
193  MakeStatus();
194  } else {
195  MakeStatus(std::move(other.status_));
196  }
197  }
198 
199  template <typename... Args>
201  : data_(std::forward<Args>(args)...) {
202  MakeStatus();
203  }
204 
205  explicit StatusOrData(const T& value) : data_(value) {
206  MakeStatus();
207  }
208  explicit StatusOrData(T&& value) : data_(std::move(value)) {
209  MakeStatus();
210  }
211 
212  template <typename U,
214  int> = 0>
215  explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
216  EnsureNotOk();
217  }
218 
220  if (this == &other) return *this;
221  if (other.ok())
222  Assign(other.data_);
223  else
224  AssignStatus(other.status_);
225  return *this;
226  }
227 
229  if (this == &other) return *this;
230  if (other.ok())
231  Assign(std::move(other.data_));
232  else
233  AssignStatus(std::move(other.status_));
234  return *this;
235  }
236 
238  if (ok()) {
239  status_.~Status();
240  data_.~T();
241  } else {
242  status_.~Status();
243  }
244  }
245 
246  template <typename U>
247  void Assign(U&& value) {
248  if (ok()) {
249  data_ = std::forward<U>(value);
250  } else {
251  MakeValue(std::forward<U>(value));
252  status_ = OkStatus();
253  }
254  }
255 
256  template <typename U>
257  void AssignStatus(U&& v) {
258  Clear();
259  status_ = static_cast<absl::Status>(std::forward<U>(v));
260  EnsureNotOk();
261  }
262 
263  bool ok() const { return status_.ok(); }
264 
265  protected:
266  // status_ will always be active after the constructor.
267  // We make it a union to be able to initialize exactly how we need without
268  // waste.
269  // Eg. in the copy constructor we use the default constructor of Status in
270  // the ok() path to avoid an extra Ref call.
271  union {
273  };
274 
275  // data_ is active iff status_.ok()==true
276  struct Dummy {};
277  union {
278  // When T is const, we need some non-const object we can cast to void* for
279  // the placement new. dummy_ is that object.
282  };
283 
284  void Clear() {
285  if (ok()) data_.~T();
286  }
287 
288  void EnsureOk() const {
290  }
291 
292  void EnsureNotOk() {
294  }
295 
296  // Construct the value (ie. data_) through placement new with the passed
297  // argument.
298  template <typename... Arg>
299  void MakeValue(Arg&&... arg) {
300  internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
301  }
302 
303  // Construct the status (ie. status_) through placement new with the passed
304  // argument.
305  template <typename... Args>
306  void MakeStatus(Args&&... args) {
307  internal_statusor::PlacementNew<Status>(&status_,
308  std::forward<Args>(args)...);
309  }
310 };
311 
312 // Helper base classes to allow implicitly deleted constructors and assignment
313 // operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
314 // the copy constructor when T is not copy constructible and `StatusOr` will
315 // inherit that behavior implicitly.
317 struct CopyCtorBase {
318  CopyCtorBase() = default;
319  CopyCtorBase(const CopyCtorBase&) = default;
320  CopyCtorBase(CopyCtorBase&&) = default;
321  CopyCtorBase& operator=(const CopyCtorBase&) = default;
322  CopyCtorBase& operator=(CopyCtorBase&&) = default;
323 };
324 
325 template <typename T>
326 struct CopyCtorBase<T, false> {
327  CopyCtorBase() = default;
328  CopyCtorBase(const CopyCtorBase&) = delete;
329  CopyCtorBase(CopyCtorBase&&) = default;
330  CopyCtorBase& operator=(const CopyCtorBase&) = default;
331  CopyCtorBase& operator=(CopyCtorBase&&) = default;
332 };
333 
335 struct MoveCtorBase {
336  MoveCtorBase() = default;
337  MoveCtorBase(const MoveCtorBase&) = default;
338  MoveCtorBase(MoveCtorBase&&) = default;
339  MoveCtorBase& operator=(const MoveCtorBase&) = default;
340  MoveCtorBase& operator=(MoveCtorBase&&) = default;
341 };
342 
343 template <typename T>
344 struct MoveCtorBase<T, false> {
345  MoveCtorBase() = default;
346  MoveCtorBase(const MoveCtorBase&) = default;
347  MoveCtorBase(MoveCtorBase&&) = delete;
348  MoveCtorBase& operator=(const MoveCtorBase&) = default;
349  MoveCtorBase& operator=(MoveCtorBase&&) = default;
350 };
351 
355  CopyAssignBase() = default;
356  CopyAssignBase(const CopyAssignBase&) = default;
357  CopyAssignBase(CopyAssignBase&&) = default;
358  CopyAssignBase& operator=(const CopyAssignBase&) = default;
360 };
361 
362 template <typename T>
364  CopyAssignBase() = default;
365  CopyAssignBase(const CopyAssignBase&) = default;
366  CopyAssignBase(CopyAssignBase&&) = default;
367  CopyAssignBase& operator=(const CopyAssignBase&) = delete;
369 };
370 
374  MoveAssignBase() = default;
375  MoveAssignBase(const MoveAssignBase&) = default;
376  MoveAssignBase(MoveAssignBase&&) = default;
377  MoveAssignBase& operator=(const MoveAssignBase&) = default;
379 };
380 
381 template <typename T>
383  MoveAssignBase() = default;
384  MoveAssignBase(const MoveAssignBase&) = default;
385  MoveAssignBase(MoveAssignBase&&) = default;
386  MoveAssignBase& operator=(const MoveAssignBase&) = default;
388 };
389 
391 
392 } // namespace internal_statusor
394 } // namespace absl
395 
396 #endif // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
ABSL_PREDICT_FALSE
#define ABSL_PREDICT_FALSE(x)
Definition: abseil-cpp/absl/base/optimization.h:180
absl::internal_statusor::StatusOrData::Clear
void Clear()
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:284
absl::internal_statusor::CopyAssignBase
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:354
absl::internal_statusor::StatusOrData
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:154
absl::internal_statusor::StatusOrData::MakeValue
void MakeValue(Arg &&... arg)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:299
absl::internal_statusor::StatusOrData::status_
Status status_
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:272
absl::remove_cv_t
typename std::remove_cv< T >::type remove_cv_t
Definition: abseil-cpp/absl/meta/type_traits.h:579
absl::internal_statusor::HasConversionOperatorToStatusOr
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:36
ABSL_ATTRIBUTE_NORETURN
#define ABSL_ATTRIBUTE_NORETURN
Definition: abseil-cpp/absl/base/attributes.h:203
absl::internal_statusor::StatusOrData::Assign
void Assign(U &&value)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:247
absl::internal_statusor::StatusOrData::operator=
StatusOrData & operator=(const StatusOrData &other)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:219
false
#define false
Definition: setup_once.h:323
test
Definition: spinlock_test.cc:36
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
absl::conditional_t
typename std::conditional< B, T, F >::type conditional_t
Definition: abseil-cpp/absl/meta/type_traits.h:634
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
absl::internal_statusor::CopyCtorBase::operator=
CopyCtorBase & operator=(const CopyCtorBase &)=default
absl::internal_statusor::StatusOrData::operator=
StatusOrData & operator=(StatusOrData &&other)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:228
absl::OkStatus
Status OkStatus()
Definition: third_party/abseil-cpp/absl/status/status.h:882
status
absl::Status status
Definition: rls.cc:251
absl::negation
Definition: abseil-cpp/absl/meta/type_traits.h:266
absl::internal_statusor::StatusOrData::dummy_
Dummy dummy_
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:280
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(absl::in_place_t, Args &&... args)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:200
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(const T &value)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:205
absl::internal_statusor::MoveAssignBase
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:373
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(T &&value)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:208
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
Arg
Arg(64) -> Arg(128) ->Arg(256) ->Arg(512) ->Arg(1024) ->Arg(1536) ->Arg(2048) ->Arg(3072) ->Arg(4096) ->Arg(5120) ->Arg(6144) ->Arg(7168)
absl::internal_statusor::Helper
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:135
T
#define T(upbtypeconst, upbtype, ctype, default_value)
absl::internal_statusor::test
void test(char(*)[sizeof(std::declval< U >().operator absl::StatusOr< T >())])
ABSL_MUST_USE_RESULT
#define ABSL_MUST_USE_RESULT
Definition: abseil-cpp/absl/base/attributes.h:441
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(StatusOrData< U > &&other)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:190
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::internal_statusor::IsForwardingAssignmentAmbiguous
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:108
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(U &&v)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:215
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
hpack_encoder_fixtures::Args
Args({0, 16384})
absl::internal_statusor::StatusOrData::AssignStatus
void AssignStatus(U &&v)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:257
absl::internal_statusor::StatusOrData::data_
T data_
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:281
testing::gmock_generated_actions_test::Dummy
int Dummy(bool flag)
Definition: bloaty/third_party/googletest/googlemock/test/gmock-generated-actions_test.cc:492
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(const StatusOrData &other)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:161
arg
Definition: cmdline.cc:40
absl::internal_statusor::Helper::Crash
static ABSL_ATTRIBUTE_NORETURN void Crash(const absl::Status &status)
Definition: abseil-cpp/absl/status/statusor.cc:82
absl::internal_statusor::StatusOrData::EnsureOk
void EnsureOk() const
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:288
absl::internal_statusor::CopyAssignBase::operator=
CopyAssignBase & operator=(const CopyAssignBase &)=default
absl::internal_statusor::MoveCtorBase
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:335
value
const char * value
Definition: hpack_parser_table.cc:165
absl::internal_statusor::IsDirectInitializationAmbiguous
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:70
absl::Status
ABSL_NAMESPACE_BEGIN class ABSL_MUST_USE_RESULT Status
Definition: abseil-cpp/absl/status/internal/status_internal.h:36
absl::internal_statusor::CopyAssignBase::CopyAssignBase
CopyAssignBase()=default
absl::internal_statusor::StatusOrData::EnsureNotOk
void EnsureNotOk()
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:292
absl::internal_statusor::MoveCtorBase::operator=
MoveCtorBase & operator=(const MoveCtorBase &)=default
absl::internal_statusor::CopyCtorBase::CopyCtorBase
CopyCtorBase()=default
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(const StatusOrData< U > &other)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:180
absl::Status
Definition: third_party/abseil-cpp/absl/status/status.h:424
absl::internal_statusor::args
Args && args
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:146
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
absl::internal_statusor::ThrowBadStatusOrAccess
ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status)
Definition: abseil-cpp/absl/status/statusor.cc:89
absl::internal_statusor::MoveAssignBase::operator=
MoveAssignBase & operator=(const MoveAssignBase &)=default
absl::disjunction
Definition: abseil-cpp/absl/meta/type_traits.h:249
absl::Status::ok
ABSL_MUST_USE_RESULT bool ok() const
Definition: third_party/abseil-cpp/absl/status/status.h:802
absl::internal_statusor::StatusOrData::ok
bool ok() const
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:263
absl::internal_statusor::MoveCtorBase::MoveCtorBase
MoveCtorBase()=default
absl::internal_statusor::CopyCtorBase
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:317
absl::internal_statusor::StatusOrData::Dummy
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:276
absl::internal_statusor::Helper::HandleInvalidStatusCtorArg
static void HandleInvalidStatusCtorArg(Status *)
Definition: abseil-cpp/absl/status/statusor.cc:70
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::in_place_t
Definition: abseil-cpp/absl/utility/utility.h:174
absl::forward
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:230
absl::StatusOr
Definition: abseil-cpp/absl/status/statusor.h:187
absl::internal_statusor::ABSL_ATTRIBUTE_NONNULL
ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void *p
absl::internal_statusor::MoveAssignBase::MoveAssignBase
MoveAssignBase()=default
absl::internal_statusor::StatusOrData::StatusOrData
friend class StatusOrData
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:156
absl::internal_statusor::StatusOrData::MakeStatus
void MakeStatus(Args &&... args)
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:306
absl::internal_statusor::StatusOrData::StatusOrData
StatusOrData(StatusOrData &&other) noexcept
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:170
absl::Status::~Status
~Status()
Definition: third_party/abseil-cpp/absl/status/status.h:800
absl::internal_statusor::StatusOrData::~StatusOrData
~StatusOrData()
Definition: abseil-cpp/absl/status/internal/statusor_internal.h:237


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:18