• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 has also released an `absl::variant` type (a C++11 compatible version
51 // of the C++17 `std::variant`), which is generally preferred for use over
52 // `absl::any`.
53 #ifndef ABSL_TYPES_ANY_H_
54 #define ABSL_TYPES_ANY_H_
55 
56 #include "absl/base/attributes.h"
57 #include "absl/base/config.h"
58 #include "absl/utility/utility.h"
59 
60 #ifdef ABSL_USES_STD_ANY
61 
62 #include <any>  // IWYU pragma: export
63 
64 namespace absl {
65 ABSL_NAMESPACE_BEGIN
66 using std::any;
67 using std::any_cast;
68 using std::bad_any_cast;
69 using std::make_any;
70 ABSL_NAMESPACE_END
71 }  // namespace absl
72 
73 #else  // ABSL_USES_STD_ANY
74 
75 #include <algorithm>
76 #include <cstddef>
77 #include <initializer_list>
78 #include <memory>
79 #include <stdexcept>
80 #include <type_traits>
81 #include <typeinfo>
82 #include <utility>
83 
84 #include "absl/base/internal/fast_type_id.h"
85 #include "absl/meta/type_traits.h"
86 #include "absl/types/bad_any_cast.h"
87 
88 namespace absl {
89 ABSL_NAMESPACE_BEGIN
90 
91 class any;
92 
93 // swap()
94 //
95 // Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
96 // `absl::any` types.
97 void swap(any& x, any& y) noexcept;
98 
99 // make_any()
100 //
101 // Constructs an `absl::any` of type `T` with the given arguments.
102 template <typename T, typename... Args>
103 any make_any(Args&&... args);
104 
105 // Overload of `absl::make_any()` for constructing an `absl::any` type from an
106 // initializer list.
107 template <typename T, typename U, typename... Args>
108 any make_any(std::initializer_list<U> il, Args&&... args);
109 
110 // any_cast()
111 //
112 // Statically casts the value of a `const absl::any` type to the given type.
113 // This function will throw `absl::bad_any_cast` if the stored value type of the
114 // `absl::any` does not match the cast.
115 //
116 // `any_cast()` can also be used to get a reference to the internal storage iff
117 // a reference type is passed as its `ValueType`:
118 //
119 // Example:
120 //
121 //   absl::any my_any = std::vector<int>();
122 //   absl::any_cast<std::vector<int>&>(my_any).push_back(42);
123 template <typename ValueType>
124 ValueType any_cast(const any& operand);
125 
126 // Overload of `any_cast()` to statically cast the value of a non-const
127 // `absl::any` type to the given type. This function will throw
128 // `absl::bad_any_cast` if the stored value type of the `absl::any` does not
129 // match the cast.
130 template <typename ValueType>
131 ValueType any_cast(any& operand);  // NOLINT(runtime/references)
132 
133 // Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
134 // type. This function will throw `absl::bad_any_cast` if the stored value type
135 // of the `absl::any` does not match the cast.
136 template <typename ValueType>
137 ValueType any_cast(any&& operand);
138 
139 // Overload of `any_cast()` to statically cast the value of a const pointer
140 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
141 // type of the `absl::any` does not match the cast.
142 template <typename ValueType>
143 const ValueType* any_cast(const any* operand) noexcept;
144 
145 // Overload of `any_cast()` to statically cast the value of a pointer
146 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
147 // type of the `absl::any` does not match the cast.
148 template <typename ValueType>
149 ValueType* any_cast(any* operand) noexcept;
150 
151 // -----------------------------------------------------------------------------
152 // absl::any
153 // -----------------------------------------------------------------------------
154 //
155 // An `absl::any` object provides the facility to either store an instance of a
156 // type, known as the "contained object", or no value. An `absl::any` is used to
157 // store values of types that are unknown at compile time. The `absl::any`
158 // object, when containing a value, must contain a value type; storing a
159 // reference type is neither desired nor supported.
160 //
161 // An `absl::any` can only store a type that is copy-constructible; move-only
162 // types are not allowed within an `any` object.
163 //
164 // Example:
165 //
166 //   auto a = absl::any(65);                 // Literal, copyable
167 //   auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
168 //   std::unique_ptr<Foo> my_foo;
169 //   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructible
170 //
171 // Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
172 // context) to remove const-volatile qualifiers (known as "cv qualifiers"),
173 // decay functions to function pointers, etc. We essentially "decay" a given
174 // type into its essential type.
175 //
176 // `absl::any` makes use of decayed types when determining the basic type `T` of
177 // the value to store in the any's contained object. In the documentation below,
178 // we explicitly denote this by using the phrase "a decayed type of `T`".
179 //
180 // Example:
181 //
182 //   const int a = 4;
183 //   absl::any foo(a);  // Decay ensures we store an "int", not a "const int&".
184 //
185 //   void my_function() {}
186 //   absl::any bar(my_function);  // Decay ensures we store a function pointer.
187 //
188 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
189 // and is designed to be a drop-in replacement for code compliant with C++17.
190 class any {
191  private:
192   template <typename T>
193   struct IsInPlaceType;
194 
195  public:
196   // Constructors
197 
198   // Constructs an empty `absl::any` object (`any::has_value()` will return
199   // `false`).
200   constexpr any() noexcept;
201 
202   // Copy constructs an `absl::any` object with a "contained object" of the
203   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
204   // `false`.
any(const any & other)205   any(const any& other)
206       : obj_(other.has_value() ? other.obj_->Clone()
207                                : std::unique_ptr<ObjInterface>()) {}
208 
209   // Move constructs an `absl::any` object with a "contained object" of the
210   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
211   // `false`).
212   any(any&& other) noexcept = default;
213 
214   // Constructs an `absl::any` object with a "contained object" of the decayed
215   // type of `T`, which is initialized via `std::forward<T>(value)`.
216   //
217   // This constructor will not participate in overload resolution if the
218   // decayed type of `T` is not copy-constructible.
219   template <
220       typename T, typename VT = absl::decay_t<T>,
221       absl::enable_if_t<!absl::disjunction<
222           std::is_same<any, VT>, IsInPlaceType<VT>,
223           absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr>
any(T && value)224   any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
225 
226   // Constructs an `absl::any` object with a "contained object" of the decayed
227   // type of `T`, which is initialized via `std::forward<T>(value)`.
228   template <typename T, typename... Args, typename VT = absl::decay_t<T>,
229             absl::enable_if_t<absl::conjunction<
230                 std::is_copy_constructible<VT>,
231                 std::is_constructible<VT, Args...>>::value>* = nullptr>
any(in_place_type_t<T>,Args &&...args)232   explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
233       : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
234 
235   // Constructs an `absl::any` object with a "contained object" of the passed
236   // type `VT` as a decayed type of `T`. `VT` is initialized as if
237   // direct-non-list-initializing an object of type `VT` with the arguments
238   // `initializer_list, std::forward<Args>(args)...`.
239   template <
240       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
241       absl::enable_if_t<
242           absl::conjunction<std::is_copy_constructible<VT>,
243                             std::is_constructible<VT, std::initializer_list<U>&,
244                                                   Args...>>::value>* = nullptr>
any(in_place_type_t<T>,std::initializer_list<U> ilist,Args &&...args)245   explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
246                Args&&... args)
247       : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
248 
249   // Assignment operators
250 
251   // Copy assigns an `absl::any` object with a "contained object" of the
252   // passed type.
253   any& operator=(const any& rhs) {
254     any(rhs).swap(*this);
255     return *this;
256   }
257 
258   // Move assigns an `absl::any` object with a "contained object" of the
259   // passed type. `rhs` is left in a valid but otherwise unspecified state.
260   any& operator=(any&& rhs) noexcept {
261     any(std::move(rhs)).swap(*this);
262     return *this;
263   }
264 
265   // Assigns an `absl::any` object with a "contained object" of the passed type.
266   template <typename T, typename VT = absl::decay_t<T>,
267             absl::enable_if_t<absl::conjunction<
268                 absl::negation<std::is_same<VT, any>>,
269                 std::is_copy_constructible<VT>>::value>* = nullptr>
270   any& operator=(T&& rhs) {
271     any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
272     tmp.swap(*this);
273     return *this;
274   }
275 
276   // Modifiers
277 
278   // any::emplace()
279   //
280   // Emplaces a value within an `absl::any` object by calling `any::reset()`,
281   // initializing the contained value as if direct-non-list-initializing an
282   // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
283   // returning a reference to the new contained value.
284   //
285   // Note: If an exception is thrown during the call to `VT`'s constructor,
286   // `*this` does not contain a value, and any previously contained value has
287   // been destroyed.
288   template <
289       typename T, typename... Args, typename VT = absl::decay_t<T>,
290       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
291                         std::is_constructible<VT, Args...>::value>* = nullptr>
emplace(Args &&...args)292   VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
293     reset();  // NOTE: reset() is required here even in the world of exceptions.
294     Obj<VT>* const object_ptr =
295         new Obj<VT>(in_place, std::forward<Args>(args)...);
296     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
297     return object_ptr->value;
298   }
299 
300   // Overload of `any::emplace()` to emplace a value within an `absl::any`
301   // object by calling `any::reset()`, initializing the contained value as if
302   // direct-non-list-initializing an object of type `VT` with the arguments
303   // `initializer_list, std::forward<Args>(args)...`, and returning a reference
304   // to the new contained value.
305   //
306   // Note: If an exception is thrown during the call to `VT`'s constructor,
307   // `*this` does not contain a value, and any previously contained value has
308   // been destroyed. The function shall not participate in overload resolution
309   // unless `is_copy_constructible_v<VT>` is `true` and
310   // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
311   template <
312       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
313       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
314                         std::is_constructible<VT, std::initializer_list<U>&,
315                                               Args...>::value>* = nullptr>
emplace(std::initializer_list<U> ilist,Args &&...args)316   VT& emplace(std::initializer_list<U> ilist,
317               Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
318     reset();  // NOTE: reset() is required here even in the world of exceptions.
319     Obj<VT>* const object_ptr =
320         new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
321     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
322     return object_ptr->value;
323   }
324 
325   // any::reset()
326   //
327   // Resets the state of the `absl::any` object, destroying the contained object
328   // if present.
reset()329   void reset() noexcept { obj_ = nullptr; }
330 
331   // any::swap()
332   //
333   // Swaps the passed value and the value of this `absl::any` object.
swap(any & other)334   void swap(any& other) noexcept { obj_.swap(other.obj_); }
335 
336   // Observers
337 
338   // any::has_value()
339   //
340   // Returns `true` if the `any` object has a contained value, otherwise
341   // returns `false`.
has_value()342   bool has_value() const noexcept { return obj_ != nullptr; }
343 
344 #ifdef ABSL_INTERNAL_HAS_RTTI
345   // Returns: typeid(T) if *this has a contained object of type T, otherwise
346   // typeid(void).
type()347   const std::type_info& type() const noexcept {
348     if (has_value()) {
349       return obj_->Type();
350     }
351 
352     return typeid(void);
353   }
354 #endif  // ABSL_INTERNAL_HAS_RTTI
355 
356  private:
357   // Tagged type-erased abstraction for holding a cloneable object.
358   class ObjInterface {
359    public:
360     virtual ~ObjInterface() = default;
361     virtual std::unique_ptr<ObjInterface> Clone() const = 0;
362     virtual const void* ObjTypeId() const noexcept = 0;
363 #ifdef ABSL_INTERNAL_HAS_RTTI
364     virtual const std::type_info& Type() const noexcept = 0;
365 #endif  // ABSL_INTERNAL_HAS_RTTI
366   };
367 
368   // Hold a value of some queryable type, with an ability to Clone it.
369   template <typename T>
370   class Obj : public ObjInterface {
371    public:
372     template <typename... Args>
Obj(in_place_t,Args &&...args)373     explicit Obj(in_place_t /*tag*/, Args&&... args)
374         : value(std::forward<Args>(args)...) {}
375 
Clone()376     std::unique_ptr<ObjInterface> Clone() const final {
377       return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
378     }
379 
ObjTypeId()380     const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
381 
382 #ifdef ABSL_INTERNAL_HAS_RTTI
Type()383     const std::type_info& Type() const noexcept final { return typeid(T); }
384 #endif  // ABSL_INTERNAL_HAS_RTTI
385 
386     T value;
387   };
388 
CloneObj()389   std::unique_ptr<ObjInterface> CloneObj() const {
390     if (!obj_) return nullptr;
391     return obj_->Clone();
392   }
393 
394   template <typename T>
IdForType()395   constexpr static const void* IdForType() {
396     // Note: This type dance is to make the behavior consistent with typeid.
397     using NormalizedType =
398         typename std::remove_cv<typename std::remove_reference<T>::type>::type;
399 
400     return base_internal::FastTypeId<NormalizedType>();
401   }
402 
GetObjTypeId()403   const void* GetObjTypeId() const {
404     return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
405   }
406 
407   // `absl::any` nonmember functions //
408 
409   // Description at the declaration site (top of file).
410   template <typename ValueType>
411   friend ValueType any_cast(const any& operand);
412 
413   // Description at the declaration site (top of file).
414   template <typename ValueType>
415   friend ValueType any_cast(any& operand);  // NOLINT(runtime/references)
416 
417   // Description at the declaration site (top of file).
418   template <typename T>
419   friend const T* any_cast(const any* operand) noexcept;
420 
421   // Description at the declaration site (top of file).
422   template <typename T>
423   friend T* any_cast(any* operand) noexcept;
424 
425   std::unique_ptr<ObjInterface> obj_;
426 };
427 
428 // -----------------------------------------------------------------------------
429 // Implementation Details
430 // -----------------------------------------------------------------------------
431 
432 constexpr any::any() noexcept = default;
433 
434 template <typename T>
435 struct any::IsInPlaceType : std::false_type {};
436 
437 template <typename T>
438 struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
439 
440 inline void swap(any& x, any& y) noexcept { x.swap(y); }
441 
442 // Description at the declaration site (top of file).
443 template <typename T, typename... Args>
444 any make_any(Args&&... args) {
445   return any(in_place_type_t<T>(), std::forward<Args>(args)...);
446 }
447 
448 // Description at the declaration site (top of file).
449 template <typename T, typename U, typename... Args>
450 any make_any(std::initializer_list<U> il, Args&&... args) {
451   return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
452 }
453 
454 // Description at the declaration site (top of file).
455 template <typename ValueType>
456 ValueType any_cast(const any& operand) {
457   using U = typename std::remove_cv<
458       typename std::remove_reference<ValueType>::type>::type;
459   static_assert(std::is_constructible<ValueType, const U&>::value,
460                 "Invalid ValueType");
461   auto* const result = (any_cast<U>)(&operand);
462   if (result == nullptr) {
463     any_internal::ThrowBadAnyCast();
464   }
465   return static_cast<ValueType>(*result);
466 }
467 
468 // Description at the declaration site (top of file).
469 template <typename ValueType>
470 ValueType any_cast(any& operand) {  // NOLINT(runtime/references)
471   using U = typename std::remove_cv<
472       typename std::remove_reference<ValueType>::type>::type;
473   static_assert(std::is_constructible<ValueType, U&>::value,
474                 "Invalid ValueType");
475   auto* result = (any_cast<U>)(&operand);
476   if (result == nullptr) {
477     any_internal::ThrowBadAnyCast();
478   }
479   return static_cast<ValueType>(*result);
480 }
481 
482 // Description at the declaration site (top of file).
483 template <typename ValueType>
484 ValueType any_cast(any&& operand) {
485   using U = typename std::remove_cv<
486       typename std::remove_reference<ValueType>::type>::type;
487   static_assert(std::is_constructible<ValueType, U>::value,
488                 "Invalid ValueType");
489   return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
490 }
491 
492 // Description at the declaration site (top of file).
493 template <typename T>
494 const T* any_cast(const any* operand) noexcept {
495   using U =
496       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
497   return operand && operand->GetObjTypeId() == any::IdForType<U>()
498              ? std::addressof(
499                    static_cast<const any::Obj<U>*>(operand->obj_.get())->value)
500              : nullptr;
501 }
502 
503 // Description at the declaration site (top of file).
504 template <typename T>
505 T* any_cast(any* operand) noexcept {
506   using U =
507       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
508   return operand && operand->GetObjTypeId() == any::IdForType<U>()
509              ? std::addressof(
510                    static_cast<any::Obj<U>*>(operand->obj_.get())->value)
511              : nullptr;
512 }
513 
514 ABSL_NAMESPACE_END
515 }  // namespace absl
516 
517 #endif  // ABSL_USES_STD_ANY
518 
519 #endif  // ABSL_TYPES_ANY_H_
520