any.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 // -----------------------------------------------------------------------------
17 // any.h
18 // -----------------------------------------------------------------------------
19 //
20 // This header file define the `absl::any` type for holding a type-safe value
21 // of any type. The 'absl::any` type is useful for providing a way to hold
22 // something that is, as yet, unspecified. Such unspecified types
23 // traditionally are passed between API boundaries until they are later cast to
24 // their "destination" types. To cast to such a destination type, use
25 // `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it
26 // to an explicit type; implicit conversions will throw.
27 //
28 // Example:
29 //
30 // auto a = absl::any(65);
31 // absl::any_cast<int>(a); // 65
32 // absl::any_cast<char>(a); // throws absl::bad_any_cast
33 // absl::any_cast<std::string>(a); // throws absl::bad_any_cast
34 //
35 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
36 // and is designed to be a drop-in replacement for code compliant with C++17.
37 //
38 // Traditionally, the behavior of casting to a temporary unspecified type has
39 // been accomplished with the `void *` paradigm, where the pointer was to some
40 // other unspecified type. `absl::any` provides an "owning" version of `void *`
41 // that avoids issues of pointer management.
42 //
43 // Note: just as in the case of `void *`, use of `absl::any` (and its C++17
44 // version `std::any`) is a code smell indicating that your API might not be
45 // constructed correctly. We have seen that most uses of `any` are unwarranted,
46 // and `absl::any`, like `std::any`, is difficult to use properly. Before using
47 // this abstraction, make sure that you should not instead be rewriting your
48 // code to be more specific.
49 //
50 // Abseil expects to release an `absl::variant` type shortly (a C++11 compatible
51 // version of the C++17 `std::variant), which is generally preferred for use
52 // over `absl::any`.
53 #ifndef ABSL_TYPES_ANY_H_
54 #define ABSL_TYPES_ANY_H_
55 
56 #include "absl/base/config.h"
57 #include "absl/utility/utility.h"
58 
59 #ifdef ABSL_HAVE_STD_ANY
60 
61 #include <any> // IWYU pragma: export
62 
63 namespace absl {
64 using std::any;
65 using std::any_cast;
66 using std::bad_any_cast;
67 using std::make_any;
68 } // namespace absl
69 
70 #else // ABSL_HAVE_STD_ANY
71 
72 #include <algorithm>
73 #include <cstddef>
74 #include <initializer_list>
75 #include <memory>
76 #include <stdexcept>
77 #include <type_traits>
78 #include <typeinfo>
79 #include <utility>
80 
81 #include "absl/base/macros.h"
82 #include "absl/meta/type_traits.h"
84 
85 // NOTE: This macro is an implementation detail that is undefined at the bottom
86 // of the file. It is not intended for expansion directly from user code.
87 #ifdef ABSL_ANY_DETAIL_HAS_RTTI
88 #error ABSL_ANY_DETAIL_HAS_RTTI cannot be directly set
89 #elif !defined(__GNUC__) || defined(__GXX_RTTI)
90 #define ABSL_ANY_DETAIL_HAS_RTTI 1
91 #endif // !defined(__GNUC__) || defined(__GXX_RTTI)
92 
93 namespace absl {
94 
95 namespace any_internal {
96 
97 template <typename Type>
98 struct TypeTag {
99  constexpr static char dummy_var = 0;
100 };
101 
102 template <typename Type>
103 constexpr char TypeTag<Type>::dummy_var;
104 
105 // FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
106 // passed in type. These are meant to be good match for keys into maps or
107 // straight up comparisons.
108 template<typename Type>
109 constexpr inline const void* FastTypeId() {
110  return &TypeTag<Type>::dummy_var;
111 }
112 
113 } // namespace any_internal
114 
115 class any;
116 
117 // swap()
118 //
119 // Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
120 // `absl::any` types.
121 void swap(any& x, any& y) noexcept;
122 
123 // make_any()
124 //
125 // Constructs an `absl::any` of type `T` with the given arguments.
126 template <typename T, typename... Args>
127 any make_any(Args&&... args);
128 
129 // Overload of `absl::make_any()` for constructing an `absl::any` type from an
130 // initializer list.
131 template <typename T, typename U, typename... Args>
132 any make_any(std::initializer_list<U> il, Args&&... args);
133 
134 // any_cast()
135 //
136 // Statically casts the value of a `const absl::any` type to the given type.
137 // This function will throw `absl::bad_any_cast` if the stored value type of the
138 // `absl::any` does not match the cast.
139 //
140 // `any_cast()` can also be used to get a reference to the internal storage iff
141 // a reference type is passed as its `ValueType`:
142 //
143 // Example:
144 //
145 // absl::any my_any = std::vector<int>();
146 // absl::any_cast<std::vector<int>&>(my_any).push_back(42);
147 template <typename ValueType>
148 ValueType any_cast(const any& operand);
149 
150 // Overload of `any_cast()` to statically cast the value of a non-const
151 // `absl::any` type to the given type. This function will throw
152 // `absl::bad_any_cast` if the stored value type of the `absl::any` does not
153 // match the cast.
154 template <typename ValueType>
155 ValueType any_cast(any& operand); // NOLINT(runtime/references)
156 
157 // Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
158 // type. This function will throw `absl::bad_any_cast` if the stored value type
159 // of the `absl::any` does not match the cast.
160 template <typename ValueType>
161 ValueType any_cast(any&& operand);
162 
163 // Overload of `any_cast()` to statically cast the value of a const pointer
164 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
165 // type of the `absl::any` does not match the cast.
166 template <typename ValueType>
167 const ValueType* any_cast(const any* operand) noexcept;
168 
169 // Overload of `any_cast()` to statically cast the value of a pointer
170 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
171 // type of the `absl::any` does not match the cast.
172 template <typename ValueType>
173 ValueType* any_cast(any* operand) noexcept;
174 
175 // -----------------------------------------------------------------------------
176 // absl::any
177 // -----------------------------------------------------------------------------
178 //
179 // An `absl::any` object provides the facility to either store an instance of a
180 // type, known as the "contained object", or no value. An `absl::any` is used to
181 // store values of types that are unknown at compile time. The `absl::any`
182 // object, when containing a value, must contain a value type; storing a
183 // reference type is neither desired nor supported.
184 //
185 // An `absl::any` can only store a type that is copy-constructable; move-only
186 // types are not allowed within an `any` object.
187 //
188 // Example:
189 //
190 // auto a = absl::any(65); // Literal, copyable
191 // auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
192 // std::unique_ptr<Foo> my_foo;
193 // auto c = absl::any(std::move(my_foo)); // Error, not copy-constructable
194 //
195 // Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
196 // context) to remove const-volatile qualifiers (known as "cv qualifiers"),
197 // decay functions to function pointers, etc. We essentially "decay" a given
198 // type into its essential type.
199 //
200 // `absl::any` makes use of decayed types when determining the basic type `T` of
201 // the value to store in the any's contained object. In the documentation below,
202 // we explicitly denote this by using the phrase "a decayed type of `T`".
203 //
204 // Example:
205 //
206 // const int a = 4;
207 // absl::any foo(a); // Decay ensures we store an "int", not a "const int&".
208 //
209 // void my_function() {}
210 // absl::any bar(my_function); // Decay ensures we store a function pointer.
211 //
212 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
213 // and is designed to be a drop-in replacement for code compliant with C++17.
214 class any {
215  private:
216  template <typename T>
218 
219  public:
220  // Constructors
221 
222  // Constructs an empty `absl::any` object (`any::has_value()` will return
223  // `false`).
224  constexpr any() noexcept;
225 
226  // Copy constructs an `absl::any` object with a "contained object" of the
227  // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
228  // `false`.
229  any(const any& other)
230  : obj_(other.has_value() ? other.obj_->Clone()
231  : std::unique_ptr<ObjInterface>()) {}
232 
233  // Move constructs an `absl::any` object with a "contained object" of the
234  // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
235  // `false`).
236  any(any&& other) noexcept = default;
237 
238  // Constructs an `absl::any` object with a "contained object" of the decayed
239  // type of `T`, which is initialized via `std::forward<T>(value)`.
240  //
241  // This constructor will not participate in overload resolution if the
242  // decayed type of `T` is not copy-constructible.
243  template <
244  typename T, typename VT = absl::decay_t<T>,
246  std::is_same<any, VT>, IsInPlaceType<VT>,
248  any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
249 
250  // Constructs an `absl::any` object with a "contained object" of the decayed
251  // type of `T`, which is initialized via `std::forward<T>(value)`.
252  template <typename T, typename... Args, typename VT = absl::decay_t<T>,
254  std::is_copy_constructible<VT>,
255  std::is_constructible<VT, Args...>>::value>* = nullptr>
256  explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
257  : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
258 
259  // Constructs an `absl::any` object with a "contained object" of the passed
260  // type `VT` as a decayed type of `T`. `VT` is initialized as if
261  // direct-non-list-initializing an object of type `VT` with the arguments
262  // `initializer_list, std::forward<Args>(args)...`.
263  template <
264  typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
267  std::is_constructible<VT, std::initializer_list<U>&,
268  Args...>>::value>* = nullptr>
269  explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
270  Args&&... args)
271  : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
272 
273  // Assignment operators
274 
275  // Copy assigns an `absl::any` object with a "contained object" of the
276  // passed type.
277  any& operator=(const any& rhs) {
278  any(rhs).swap(*this);
279  return *this;
280  }
281 
282  // Move assigns an `absl::any` object with a "contained object" of the
283  // passed type. `rhs` is left in a valid but otherwise unspecified state.
284  any& operator=(any&& rhs) noexcept {
285  any(std::move(rhs)).swap(*this);
286  return *this;
287  }
288 
289  // Assigns an `absl::any` object with a "contained object" of the passed type.
290  template <typename T, typename VT = absl::decay_t<T>,
291  absl::enable_if_t<absl::conjunction<
292  absl::negation<std::is_same<VT, any>>,
293  std::is_copy_constructible<VT>>::value>* = nullptr>
294  any& operator=(T&& rhs) {
295  any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
296  tmp.swap(*this);
297  return *this;
298  }
299 
300  // Modifiers
301 
302  // any::emplace()
303  //
304  // Emplaces a value within an `absl::any` object by calling `any::reset()`,
305  // initializing the contained value as if direct-non-list-initializing an
306  // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
307  // returning a reference to the new contained value.
308  //
309  // Note: If an exception is thrown during the call to `VT`'s constructor,
310  // `*this` does not contain a value, and any previously contained value has
311  // been destroyed.
312  template <
313  typename T, typename... Args, typename VT = absl::decay_t<T>,
315  std::is_constructible<VT, Args...>::value>* = nullptr>
316  VT& emplace(Args&&... args) {
317  reset(); // NOTE: reset() is required here even in the world of exceptions.
318  Obj<VT>* const object_ptr =
319  new Obj<VT>(in_place, std::forward<Args>(args)...);
320  obj_ = std::unique_ptr<ObjInterface>(object_ptr);
321  return object_ptr->value;
322  }
323 
324  // Overload of `any::emplace()` to emplace a value within an `absl::any`
325  // object by calling `any::reset()`, initializing the contained value as if
326  // direct-non-list-initializing an object of type `VT` with the arguments
327  // `initializer_list, std::forward<Args>(args)...`, and returning a reference
328  // to the new contained value.
329  //
330  // Note: If an exception is thrown during the call to `VT`'s constructor,
331  // `*this` does not contain a value, and any previously contained value has
332  // been destroyed. The function shall not participate in overload resolution
333  // unless `is_copy_constructible_v<VT>` is `true` and
334  // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
335  template <
336  typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
338  std::is_constructible<VT, std::initializer_list<U>&,
339  Args...>::value>* = nullptr>
340  VT& emplace(std::initializer_list<U> ilist, Args&&... args) {
341  reset(); // NOTE: reset() is required here even in the world of exceptions.
342  Obj<VT>* const object_ptr =
343  new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
344  obj_ = std::unique_ptr<ObjInterface>(object_ptr);
345  return object_ptr->value;
346  }
347 
348  // any::reset()
349  //
350  // Resets the state of the `absl::any` object, destroying the contained object
351  // if present.
352  void reset() noexcept { obj_ = nullptr; }
353 
354  // any::swap()
355  //
356  // Swaps the passed value and the value of this `absl::any` object.
357  void swap(any& other) noexcept { obj_.swap(other.obj_); }
358 
359  // Observers
360 
361  // any::has_value()
362  //
363  // Returns `true` if the `any` object has a contained value, otherwise
364  // returns `false`.
365  bool has_value() const noexcept { return obj_ != nullptr; }
366 
367 #if ABSL_ANY_DETAIL_HAS_RTTI
368  // Returns: typeid(T) if *this has a contained object of type T, otherwise
369  // typeid(void).
370  const std::type_info& type() const noexcept {
371  if (has_value()) {
372  return obj_->Type();
373  }
374 
375  return typeid(void);
376  }
377 #endif // ABSL_ANY_DETAIL_HAS_RTTI
378 
379  private:
380  // Tagged type-erased abstraction for holding a cloneable object.
381  class ObjInterface {
382  public:
383  virtual ~ObjInterface() = default;
384  virtual std::unique_ptr<ObjInterface> Clone() const = 0;
385  virtual const void* ObjTypeId() const noexcept = 0;
386 #if ABSL_ANY_DETAIL_HAS_RTTI
387  virtual const std::type_info& Type() const noexcept = 0;
388 #endif // ABSL_ANY_DETAIL_HAS_RTTI
389  };
390 
391  // Hold a value of some queryable type, with an ability to Clone it.
392  template <typename T>
393  class Obj : public ObjInterface {
394  public:
395  template <typename... Args>
396  explicit Obj(in_place_t /*tag*/, Args&&... args)
397  : value(std::forward<Args>(args)...) {}
398 
399  std::unique_ptr<ObjInterface> Clone() const final {
400  return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
401  }
402 
403  const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
404 
405 #if ABSL_ANY_DETAIL_HAS_RTTI
406  const std::type_info& Type() const noexcept final { return typeid(T); }
407 #endif // ABSL_ANY_DETAIL_HAS_RTTI
408 
409  T value;
410  };
411 
412  std::unique_ptr<ObjInterface> CloneObj() const {
413  if (!obj_) return nullptr;
414  return obj_->Clone();
415  }
416 
417  template <typename T>
418  constexpr static const void* IdForType() {
419  // Note: This type dance is to make the behavior consistent with typeid.
420  using NormalizedType =
421  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
422 
423  return any_internal::FastTypeId<NormalizedType>();
424  }
425 
426  const void* GetObjTypeId() const {
427  return obj_ ? obj_->ObjTypeId() : any_internal::FastTypeId<void>();
428  }
429 
430  // `absl::any` nonmember functions //
431 
432  // Description at the declaration site (top of file).
433  template <typename ValueType>
434  friend ValueType any_cast(const any& operand);
435 
436  // Description at the declaration site (top of file).
437  template <typename ValueType>
438  friend ValueType any_cast(any& operand); // NOLINT(runtime/references)
439 
440  // Description at the declaration site (top of file).
441  template <typename T>
442  friend const T* any_cast(const any* operand) noexcept;
443 
444  // Description at the declaration site (top of file).
445  template <typename T>
446  friend T* any_cast(any* operand) noexcept;
447 
448  std::unique_ptr<ObjInterface> obj_;
449 };
450 
451 // -----------------------------------------------------------------------------
452 // Implementation Details
453 // -----------------------------------------------------------------------------
454 
455 constexpr any::any() noexcept = default;
456 
457 template <typename T>
458 struct any::IsInPlaceType : std::false_type {};
459 
460 template <typename T>
461 struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
462 
463 inline void swap(any& x, any& y) noexcept { x.swap(y); }
464 
465 // Description at the declaration site (top of file).
466 template <typename T, typename... Args>
467 any make_any(Args&&... args) {
468  return any(in_place_type_t<T>(), std::forward<Args>(args)...);
469 }
470 
471 // Description at the declaration site (top of file).
472 template <typename T, typename U, typename... Args>
473 any make_any(std::initializer_list<U> il, Args&&... args) {
474  return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
475 }
476 
477 // Description at the declaration site (top of file).
478 template <typename ValueType>
479 ValueType any_cast(const any& operand) {
480  using U = typename std::remove_cv<
481  typename std::remove_reference<ValueType>::type>::type;
483  "Invalid ValueType");
484  auto* const result = (any_cast<U>)(&operand);
485  if (result == nullptr) {
487  }
488  return static_cast<ValueType>(*result);
489 }
490 
491 // Description at the declaration site (top of file).
492 template <typename ValueType>
493 ValueType any_cast(any& operand) { // NOLINT(runtime/references)
494  using U = typename std::remove_cv<
495  typename std::remove_reference<ValueType>::type>::type;
497  "Invalid ValueType");
498  auto* result = (any_cast<U>)(&operand);
499  if (result == nullptr) {
501  }
502  return static_cast<ValueType>(*result);
503 }
504 
505 // Description at the declaration site (top of file).
506 template <typename ValueType>
507 ValueType any_cast(any&& operand) {
508  using U = typename std::remove_cv<
509  typename std::remove_reference<ValueType>::type>::type;
511  "Invalid ValueType");
512  return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
513 }
514 
515 // Description at the declaration site (top of file).
516 template <typename T>
517 const T* any_cast(const any* operand) noexcept {
518  return operand && operand->GetObjTypeId() == any::IdForType<T>()
519  ? std::addressof(
520  static_cast<const any::Obj<T>*>(operand->obj_.get())->value)
521  : nullptr;
522 }
523 
524 // Description at the declaration site (top of file).
525 template <typename T>
526 T* any_cast(any* operand) noexcept {
527  return operand && operand->GetObjTypeId() == any::IdForType<T>()
528  ? std::addressof(
529  static_cast<any::Obj<T>*>(operand->obj_.get())->value)
530  : nullptr;
531 }
532 
533 } // namespace absl
534 
535 #undef ABSL_ANY_DETAIL_HAS_RTTI
536 
537 #endif // ABSL_HAVE_STD_ANY
538 
539 #endif // ABSL_TYPES_ANY_H_
void reset() noexcept
Definition: any.h:352
const void * GetObjTypeId() const
Definition: any.h:426
static constexpr const void * IdForType()
Definition: any.h:418
Obj(in_place_t, Args &&... args)
Definition: any.h:396
bool has_value() const noexcept
Definition: any.h:365
any make_any(std::initializer_list< U > il, Args &&... args)
Definition: any.h:473
constexpr T && forward(absl::remove_reference_t< T > &t) noexcept
Definition: utility.h:228
any make_any(Args &&... args)
Definition: any.h:467
void swap(any &other) noexcept
Definition: any.h:357
typename std::decay< T >::type decay_t
Definition: type_traits.h:544
const void * ObjTypeId() const noexcept final
Definition: any.h:403
void * Clone(FlagOpFn op, const void *obj)
constexpr any() noexcept
any(in_place_type_t< T >, std::initializer_list< U > ilist, Args &&... args)
Definition: any.h:269
const std::type_info & Type() const noexcept final
Definition: any.h:406
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: utility.h:189
Definition: algorithm.h:29
static constexpr char dummy_var
Definition: any.h:99
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.h:547
any(T &&value)
Definition: any.h:248
Definition: any.h:214
size_t value
std::unique_ptr< ObjInterface > Clone() const final
Definition: any.h:399
std::unique_ptr< ObjInterface > CloneObj() const
Definition: any.h:412
std::unique_ptr< ObjInterface > obj_
Definition: any.h:448
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
ValueType any_cast(const any &operand)
Definition: any.h:479
const std::type_info & type() const noexcept
Definition: any.h:370
any & operator=(any &&rhs) noexcept
Definition: any.h:284
constexpr const void * FastTypeId()
Definition: any.h:109
VT & emplace(Args &&... args)
Definition: any.h:316
any & operator=(const any &rhs)
Definition: any.h:277
any(in_place_type_t< T >, Args &&... args)
Definition: any.h:256
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
T * any_cast(any *operand) noexcept
Definition: any.h:526
any & operator=(T &&rhs)
Definition: any.h:294
VT & emplace(std::initializer_list< U > ilist, Args &&... args)
Definition: any.h:340


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:17