"Fossies" - the Fresh Open Source Software Archive

Member "abseil-cpp-20230802.1/absl/types/any.h" (18 Sep 2023, 19597 Bytes) of package /linux/misc/abseil-cpp-20230802.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "any.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20230125.3_vs_20230802.0.

    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`.
  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>
  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>
  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>
  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>
  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>
  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.
  329   void reset() noexcept { obj_ = nullptr; }
  330 
  331   // any::swap()
  332   //
  333   // Swaps the passed value and the value of this `absl::any` object.
  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`.
  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).
  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>
  373     explicit Obj(in_place_t /*tag*/, Args&&... args)
  374         : value(std::forward<Args>(args)...) {}
  375 
  376     std::unique_ptr<ObjInterface> Clone() const final {
  377       return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
  378     }
  379 
  380     const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
  381 
  382 #ifdef ABSL_INTERNAL_HAS_RTTI
  383     const std::type_info& Type() const noexcept final { return typeid(T); }
  384 #endif  // ABSL_INTERNAL_HAS_RTTI
  385 
  386     T value;
  387   };
  388 
  389   std::unique_ptr<ObjInterface> CloneObj() const {
  390     if (!obj_) return nullptr;
  391     return obj_->Clone();
  392   }
  393 
  394   template <typename T>
  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 
  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_