Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:41:08

0001 //
0002 // Copyright 2017 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 //
0016 // -----------------------------------------------------------------------------
0017 // any.h
0018 // -----------------------------------------------------------------------------
0019 //
0020 // This header file define the `absl::any` type for holding a type-safe value
0021 // of any type. The 'absl::any` type is useful for providing a way to hold
0022 // something that is, as yet, unspecified. Such unspecified types
0023 // traditionally are passed between API boundaries until they are later cast to
0024 // their "destination" types. To cast to such a destination type, use
0025 // `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it
0026 // to an explicit type; implicit conversions will throw.
0027 //
0028 // Example:
0029 //
0030 //   auto a = absl::any(65);
0031 //   absl::any_cast<int>(a);         // 65
0032 //   absl::any_cast<char>(a);        // throws absl::bad_any_cast
0033 //   absl::any_cast<std::string>(a); // throws absl::bad_any_cast
0034 //
0035 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
0036 // and is designed to be a drop-in replacement for code compliant with C++17.
0037 //
0038 // Traditionally, the behavior of casting to a temporary unspecified type has
0039 // been accomplished with the `void *` paradigm, where the pointer was to some
0040 // other unspecified type. `absl::any` provides an "owning" version of `void *`
0041 // that avoids issues of pointer management.
0042 //
0043 // Note: just as in the case of `void *`, use of `absl::any` (and its C++17
0044 // version `std::any`) is a code smell indicating that your API might not be
0045 // constructed correctly. We have seen that most uses of `any` are unwarranted,
0046 // and `absl::any`, like `std::any`, is difficult to use properly. Before using
0047 // this abstraction, make sure that you should not instead be rewriting your
0048 // code to be more specific.
0049 //
0050 // Abseil has also released an `absl::variant` type (a C++11 compatible version
0051 // of the C++17 `std::variant`), which is generally preferred for use over
0052 // `absl::any`.
0053 #ifndef ABSL_TYPES_ANY_H_
0054 #define ABSL_TYPES_ANY_H_
0055 
0056 #include "absl/base/attributes.h"
0057 #include "absl/base/config.h"
0058 #include "absl/utility/utility.h"
0059 
0060 #ifdef ABSL_USES_STD_ANY
0061 
0062 #include <any>  // IWYU pragma: export
0063 
0064 namespace absl {
0065 ABSL_NAMESPACE_BEGIN
0066 using std::any;
0067 using std::any_cast;
0068 using std::bad_any_cast;
0069 using std::make_any;
0070 ABSL_NAMESPACE_END
0071 }  // namespace absl
0072 
0073 #else  // ABSL_USES_STD_ANY
0074 
0075 #include <algorithm>
0076 #include <cstddef>
0077 #include <initializer_list>
0078 #include <memory>
0079 #include <stdexcept>
0080 #include <type_traits>
0081 #include <typeinfo>
0082 #include <utility>
0083 
0084 #include "absl/base/internal/fast_type_id.h"
0085 #include "absl/meta/type_traits.h"
0086 #include "absl/types/bad_any_cast.h"
0087 
0088 namespace absl {
0089 ABSL_NAMESPACE_BEGIN
0090 
0091 class any;
0092 
0093 // swap()
0094 //
0095 // Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
0096 // `absl::any` types.
0097 void swap(any& x, any& y) noexcept;
0098 
0099 // make_any()
0100 //
0101 // Constructs an `absl::any` of type `T` with the given arguments.
0102 template <typename T, typename... Args>
0103 any make_any(Args&&... args);
0104 
0105 // Overload of `absl::make_any()` for constructing an `absl::any` type from an
0106 // initializer list.
0107 template <typename T, typename U, typename... Args>
0108 any make_any(std::initializer_list<U> il, Args&&... args);
0109 
0110 // any_cast()
0111 //
0112 // Statically casts the value of a `const absl::any` type to the given type.
0113 // This function will throw `absl::bad_any_cast` if the stored value type of the
0114 // `absl::any` does not match the cast.
0115 //
0116 // `any_cast()` can also be used to get a reference to the internal storage iff
0117 // a reference type is passed as its `ValueType`:
0118 //
0119 // Example:
0120 //
0121 //   absl::any my_any = std::vector<int>();
0122 //   absl::any_cast<std::vector<int>&>(my_any).push_back(42);
0123 template <typename ValueType>
0124 ValueType any_cast(const any& operand);
0125 
0126 // Overload of `any_cast()` to statically cast the value of a non-const
0127 // `absl::any` type to the given type. This function will throw
0128 // `absl::bad_any_cast` if the stored value type of the `absl::any` does not
0129 // match the cast.
0130 template <typename ValueType>
0131 ValueType any_cast(any& operand);  // NOLINT(runtime/references)
0132 
0133 // Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
0134 // type. This function will throw `absl::bad_any_cast` if the stored value type
0135 // of the `absl::any` does not match the cast.
0136 template <typename ValueType>
0137 ValueType any_cast(any&& operand);
0138 
0139 // Overload of `any_cast()` to statically cast the value of a const pointer
0140 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
0141 // type of the `absl::any` does not match the cast.
0142 template <typename ValueType>
0143 const ValueType* any_cast(const any* operand) noexcept;
0144 
0145 // Overload of `any_cast()` to statically cast the value of a pointer
0146 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
0147 // type of the `absl::any` does not match the cast.
0148 template <typename ValueType>
0149 ValueType* any_cast(any* operand) noexcept;
0150 
0151 // -----------------------------------------------------------------------------
0152 // absl::any
0153 // -----------------------------------------------------------------------------
0154 //
0155 // An `absl::any` object provides the facility to either store an instance of a
0156 // type, known as the "contained object", or no value. An `absl::any` is used to
0157 // store values of types that are unknown at compile time. The `absl::any`
0158 // object, when containing a value, must contain a value type; storing a
0159 // reference type is neither desired nor supported.
0160 //
0161 // An `absl::any` can only store a type that is copy-constructible; move-only
0162 // types are not allowed within an `any` object.
0163 //
0164 // Example:
0165 //
0166 //   auto a = absl::any(65);                 // Literal, copyable
0167 //   auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
0168 //   std::unique_ptr<Foo> my_foo;
0169 //   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructible
0170 //
0171 // Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
0172 // context) to remove const-volatile qualifiers (known as "cv qualifiers"),
0173 // decay functions to function pointers, etc. We essentially "decay" a given
0174 // type into its essential type.
0175 //
0176 // `absl::any` makes use of decayed types when determining the basic type `T` of
0177 // the value to store in the any's contained object. In the documentation below,
0178 // we explicitly denote this by using the phrase "a decayed type of `T`".
0179 //
0180 // Example:
0181 //
0182 //   const int a = 4;
0183 //   absl::any foo(a);  // Decay ensures we store an "int", not a "const int&".
0184 //
0185 //   void my_function() {}
0186 //   absl::any bar(my_function);  // Decay ensures we store a function pointer.
0187 //
0188 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
0189 // and is designed to be a drop-in replacement for code compliant with C++17.
0190 class any {
0191  private:
0192   template <typename T>
0193   struct IsInPlaceType;
0194 
0195  public:
0196   // Constructors
0197 
0198   // Constructs an empty `absl::any` object (`any::has_value()` will return
0199   // `false`).
0200   constexpr any() noexcept;
0201 
0202   // Copy constructs an `absl::any` object with a "contained object" of the
0203   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
0204   // `false`.
0205   any(const any& other)
0206       : obj_(other.has_value() ? other.obj_->Clone()
0207                                : std::unique_ptr<ObjInterface>()) {}
0208 
0209   // Move constructs an `absl::any` object with a "contained object" of the
0210   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
0211   // `false`).
0212   any(any&& other) noexcept = default;
0213 
0214   // Constructs an `absl::any` object with a "contained object" of the decayed
0215   // type of `T`, which is initialized via `std::forward<T>(value)`.
0216   //
0217   // This constructor will not participate in overload resolution if the
0218   // decayed type of `T` is not copy-constructible.
0219   template <
0220       typename T, typename VT = absl::decay_t<T>,
0221       absl::enable_if_t<!absl::disjunction<
0222           std::is_same<any, VT>, IsInPlaceType<VT>,
0223           absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr>
0224   any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
0225 
0226   // Constructs an `absl::any` object with a "contained object" of the decayed
0227   // type of `T`, which is initialized via `std::forward<T>(value)`.
0228   template <typename T, typename... Args, typename VT = absl::decay_t<T>,
0229             absl::enable_if_t<absl::conjunction<
0230                 std::is_copy_constructible<VT>,
0231                 std::is_constructible<VT, Args...>>::value>* = nullptr>
0232   explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
0233       : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
0234 
0235   // Constructs an `absl::any` object with a "contained object" of the passed
0236   // type `VT` as a decayed type of `T`. `VT` is initialized as if
0237   // direct-non-list-initializing an object of type `VT` with the arguments
0238   // `initializer_list, std::forward<Args>(args)...`.
0239   template <
0240       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
0241       absl::enable_if_t<
0242           absl::conjunction<std::is_copy_constructible<VT>,
0243                             std::is_constructible<VT, std::initializer_list<U>&,
0244                                                   Args...>>::value>* = nullptr>
0245   explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
0246                Args&&... args)
0247       : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
0248 
0249   // Assignment operators
0250 
0251   // Copy assigns an `absl::any` object with a "contained object" of the
0252   // passed type.
0253   any& operator=(const any& rhs) {
0254     any(rhs).swap(*this);
0255     return *this;
0256   }
0257 
0258   // Move assigns an `absl::any` object with a "contained object" of the
0259   // passed type. `rhs` is left in a valid but otherwise unspecified state.
0260   any& operator=(any&& rhs) noexcept {
0261     any(std::move(rhs)).swap(*this);
0262     return *this;
0263   }
0264 
0265   // Assigns an `absl::any` object with a "contained object" of the passed type.
0266   template <typename T, typename VT = absl::decay_t<T>,
0267             absl::enable_if_t<absl::conjunction<
0268                 absl::negation<std::is_same<VT, any>>,
0269                 std::is_copy_constructible<VT>>::value>* = nullptr>
0270   any& operator=(T&& rhs) {
0271     any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
0272     tmp.swap(*this);
0273     return *this;
0274   }
0275 
0276   // Modifiers
0277 
0278   // any::emplace()
0279   //
0280   // Emplaces a value within an `absl::any` object by calling `any::reset()`,
0281   // initializing the contained value as if direct-non-list-initializing an
0282   // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
0283   // returning a reference to the new contained value.
0284   //
0285   // Note: If an exception is thrown during the call to `VT`'s constructor,
0286   // `*this` does not contain a value, and any previously contained value has
0287   // been destroyed.
0288   template <
0289       typename T, typename... Args, typename VT = absl::decay_t<T>,
0290       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
0291                         std::is_constructible<VT, Args...>::value>* = nullptr>
0292   VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0293     reset();  // NOTE: reset() is required here even in the world of exceptions.
0294     Obj<VT>* const object_ptr =
0295         new Obj<VT>(in_place, std::forward<Args>(args)...);
0296     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
0297     return object_ptr->value;
0298   }
0299 
0300   // Overload of `any::emplace()` to emplace a value within an `absl::any`
0301   // object by calling `any::reset()`, initializing the contained value as if
0302   // direct-non-list-initializing an object of type `VT` with the arguments
0303   // `initializer_list, std::forward<Args>(args)...`, and returning a reference
0304   // to the new contained value.
0305   //
0306   // Note: If an exception is thrown during the call to `VT`'s constructor,
0307   // `*this` does not contain a value, and any previously contained value has
0308   // been destroyed. The function shall not participate in overload resolution
0309   // unless `is_copy_constructible_v<VT>` is `true` and
0310   // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
0311   template <
0312       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
0313       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
0314                         std::is_constructible<VT, std::initializer_list<U>&,
0315                                               Args...>::value>* = nullptr>
0316   VT& emplace(std::initializer_list<U> ilist,
0317               Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0318     reset();  // NOTE: reset() is required here even in the world of exceptions.
0319     Obj<VT>* const object_ptr =
0320         new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
0321     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
0322     return object_ptr->value;
0323   }
0324 
0325   // any::reset()
0326   //
0327   // Resets the state of the `absl::any` object, destroying the contained object
0328   // if present.
0329   void reset() noexcept { obj_ = nullptr; }
0330 
0331   // any::swap()
0332   //
0333   // Swaps the passed value and the value of this `absl::any` object.
0334   void swap(any& other) noexcept { obj_.swap(other.obj_); }
0335 
0336   // Observers
0337 
0338   // any::has_value()
0339   //
0340   // Returns `true` if the `any` object has a contained value, otherwise
0341   // returns `false`.
0342   bool has_value() const noexcept { return obj_ != nullptr; }
0343 
0344 #ifdef ABSL_INTERNAL_HAS_RTTI
0345   // Returns: typeid(T) if *this has a contained object of type T, otherwise
0346   // typeid(void).
0347   const std::type_info& type() const noexcept {
0348     if (has_value()) {
0349       return obj_->Type();
0350     }
0351 
0352     return typeid(void);
0353   }
0354 #endif  // ABSL_INTERNAL_HAS_RTTI
0355 
0356  private:
0357   // Tagged type-erased abstraction for holding a cloneable object.
0358   class ObjInterface {
0359    public:
0360     virtual ~ObjInterface() = default;
0361     virtual std::unique_ptr<ObjInterface> Clone() const = 0;
0362     virtual const void* ObjTypeId() const noexcept = 0;
0363 #ifdef ABSL_INTERNAL_HAS_RTTI
0364     virtual const std::type_info& Type() const noexcept = 0;
0365 #endif  // ABSL_INTERNAL_HAS_RTTI
0366   };
0367 
0368   // Hold a value of some queryable type, with an ability to Clone it.
0369   template <typename T>
0370   class Obj : public ObjInterface {
0371    public:
0372     template <typename... Args>
0373     explicit Obj(in_place_t /*tag*/, Args&&... args)
0374         : value(std::forward<Args>(args)...) {}
0375 
0376     std::unique_ptr<ObjInterface> Clone() const final {
0377       return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
0378     }
0379 
0380     const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
0381 
0382 #ifdef ABSL_INTERNAL_HAS_RTTI
0383     const std::type_info& Type() const noexcept final { return typeid(T); }
0384 #endif  // ABSL_INTERNAL_HAS_RTTI
0385 
0386     T value;
0387   };
0388 
0389   std::unique_ptr<ObjInterface> CloneObj() const {
0390     if (!obj_) return nullptr;
0391     return obj_->Clone();
0392   }
0393 
0394   template <typename T>
0395   constexpr static const void* IdForType() {
0396     // Note: This type dance is to make the behavior consistent with typeid.
0397     using NormalizedType =
0398         typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0399 
0400     return base_internal::FastTypeId<NormalizedType>();
0401   }
0402 
0403   const void* GetObjTypeId() const {
0404     return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
0405   }
0406 
0407   // `absl::any` nonmember functions //
0408 
0409   // Description at the declaration site (top of file).
0410   template <typename ValueType>
0411   friend ValueType any_cast(const any& operand);
0412 
0413   // Description at the declaration site (top of file).
0414   template <typename ValueType>
0415   friend ValueType any_cast(any& operand);  // NOLINT(runtime/references)
0416 
0417   // Description at the declaration site (top of file).
0418   template <typename T>
0419   friend const T* any_cast(const any* operand) noexcept;
0420 
0421   // Description at the declaration site (top of file).
0422   template <typename T>
0423   friend T* any_cast(any* operand) noexcept;
0424 
0425   std::unique_ptr<ObjInterface> obj_;
0426 };
0427 
0428 // -----------------------------------------------------------------------------
0429 // Implementation Details
0430 // -----------------------------------------------------------------------------
0431 
0432 constexpr any::any() noexcept = default;
0433 
0434 template <typename T>
0435 struct any::IsInPlaceType : std::false_type {};
0436 
0437 template <typename T>
0438 struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
0439 
0440 inline void swap(any& x, any& y) noexcept { x.swap(y); }
0441 
0442 // Description at the declaration site (top of file).
0443 template <typename T, typename... Args>
0444 any make_any(Args&&... args) {
0445   return any(in_place_type_t<T>(), std::forward<Args>(args)...);
0446 }
0447 
0448 // Description at the declaration site (top of file).
0449 template <typename T, typename U, typename... Args>
0450 any make_any(std::initializer_list<U> il, Args&&... args) {
0451   return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
0452 }
0453 
0454 // Description at the declaration site (top of file).
0455 template <typename ValueType>
0456 ValueType any_cast(const any& operand) {
0457   using U = typename std::remove_cv<
0458       typename std::remove_reference<ValueType>::type>::type;
0459   static_assert(std::is_constructible<ValueType, const U&>::value,
0460                 "Invalid ValueType");
0461   auto* const result = (any_cast<U>)(&operand);
0462   if (result == nullptr) {
0463     any_internal::ThrowBadAnyCast();
0464   }
0465   return static_cast<ValueType>(*result);
0466 }
0467 
0468 // Description at the declaration site (top of file).
0469 template <typename ValueType>
0470 ValueType any_cast(any& operand) {  // NOLINT(runtime/references)
0471   using U = typename std::remove_cv<
0472       typename std::remove_reference<ValueType>::type>::type;
0473   static_assert(std::is_constructible<ValueType, U&>::value,
0474                 "Invalid ValueType");
0475   auto* result = (any_cast<U>)(&operand);
0476   if (result == nullptr) {
0477     any_internal::ThrowBadAnyCast();
0478   }
0479   return static_cast<ValueType>(*result);
0480 }
0481 
0482 // Description at the declaration site (top of file).
0483 template <typename ValueType>
0484 ValueType any_cast(any&& operand) {
0485   using U = typename std::remove_cv<
0486       typename std::remove_reference<ValueType>::type>::type;
0487   static_assert(std::is_constructible<ValueType, U>::value,
0488                 "Invalid ValueType");
0489   return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
0490 }
0491 
0492 // Description at the declaration site (top of file).
0493 template <typename T>
0494 const T* any_cast(const any* operand) noexcept {
0495   using U =
0496       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0497   return operand && operand->GetObjTypeId() == any::IdForType<U>()
0498              ? std::addressof(
0499                    static_cast<const any::Obj<U>*>(operand->obj_.get())->value)
0500              : nullptr;
0501 }
0502 
0503 // Description at the declaration site (top of file).
0504 template <typename T>
0505 T* any_cast(any* operand) noexcept {
0506   using U =
0507       typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0508   return operand && operand->GetObjTypeId() == any::IdForType<U>()
0509              ? std::addressof(
0510                    static_cast<any::Obj<U>*>(operand->obj_.get())->value)
0511              : nullptr;
0512 }
0513 
0514 ABSL_NAMESPACE_END
0515 }  // namespace absl
0516 
0517 #endif  // ABSL_USES_STD_ANY
0518 
0519 #endif  // ABSL_TYPES_ANY_H_