any.h
Go to the documentation of this file.
00001 //
00002 // Copyright 2017 The Abseil Authors.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //      https://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 //
00016 // -----------------------------------------------------------------------------
00017 // any.h
00018 // -----------------------------------------------------------------------------
00019 //
00020 // This header file define the `absl::any` type for holding a type-safe value
00021 // of any type. The 'absl::any` type is useful for providing a way to hold
00022 // something that is, as yet, unspecified. Such unspecified types
00023 // traditionally are passed between API boundaries until they are later cast to
00024 // their "destination" types. To cast to such a destination type, use
00025 // `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it
00026 // to an explicit type; implicit conversions will throw.
00027 //
00028 // Example:
00029 //
00030 //   auto a = absl::any(65);
00031 //   absl::any_cast<int>(a);         // 65
00032 //   absl::any_cast<char>(a);        // throws absl::bad_any_cast
00033 //   absl::any_cast<std::string>(a); // throws absl::bad_any_cast
00034 //
00035 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
00036 // and is designed to be a drop-in replacement for code compliant with C++17.
00037 //
00038 // Traditionally, the behavior of casting to a temporary unspecified type has
00039 // been accomplished with the `void *` paradigm, where the pointer was to some
00040 // other unspecified type. `absl::any` provides an "owning" version of `void *`
00041 // that avoids issues of pointer management.
00042 //
00043 // Note: just as in the case of `void *`, use of `absl::any` (and its C++17
00044 // version `std::any`) is a code smell indicating that your API might not be
00045 // constructed correctly. We have seen that most uses of `any` are unwarranted,
00046 // and `absl::any`, like `std::any`, is difficult to use properly. Before using
00047 // this abstraction, make sure that you should not instead be rewriting your
00048 // code to be more specific.
00049 //
00050 // Abseil expects to release an `absl::variant` type shortly (a C++11 compatible
00051 // version of the C++17 `std::variant), which is generally preferred for use
00052 // over `absl::any`.
00053 #ifndef ABSL_TYPES_ANY_H_
00054 #define ABSL_TYPES_ANY_H_
00055 
00056 #include "absl/base/config.h"
00057 #include "absl/utility/utility.h"
00058 
00059 #ifdef ABSL_HAVE_STD_ANY
00060 
00061 #include <any>  // IWYU pragma: export
00062 
00063 namespace absl {
00064 using std::any;
00065 using std::any_cast;
00066 using std::bad_any_cast;
00067 using std::make_any;
00068 }  // namespace absl
00069 
00070 #else  // ABSL_HAVE_STD_ANY
00071 
00072 #include <algorithm>
00073 #include <cstddef>
00074 #include <initializer_list>
00075 #include <memory>
00076 #include <stdexcept>
00077 #include <type_traits>
00078 #include <typeinfo>
00079 #include <utility>
00080 
00081 #include "absl/base/macros.h"
00082 #include "absl/meta/type_traits.h"
00083 #include "absl/types/bad_any_cast.h"
00084 
00085 // NOTE: This macro is an implementation detail that is undefined at the bottom
00086 // of the file. It is not intended for expansion directly from user code.
00087 #ifdef ABSL_ANY_DETAIL_HAS_RTTI
00088 #error ABSL_ANY_DETAIL_HAS_RTTI cannot be directly set
00089 #elif !defined(__GNUC__) || defined(__GXX_RTTI)
00090 #define ABSL_ANY_DETAIL_HAS_RTTI 1
00091 #endif  // !defined(__GNUC__) || defined(__GXX_RTTI)
00092 
00093 namespace absl {
00094 
00095 namespace any_internal {
00096 
00097 template <typename Type>
00098 struct TypeTag {
00099   constexpr static char dummy_var = 0;
00100 };
00101 
00102 template <typename Type>
00103 constexpr char TypeTag<Type>::dummy_var;
00104 
00105 // FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
00106 // passed in type. These are meant to be good match for keys into maps or
00107 // straight up comparisons.
00108 template<typename Type>
00109 constexpr inline const void* FastTypeId() {
00110   return &TypeTag<Type>::dummy_var;
00111 }
00112 
00113 }  // namespace any_internal
00114 
00115 class any;
00116 
00117 // swap()
00118 //
00119 // Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
00120 // `absl::any` types.
00121 void swap(any& x, any& y) noexcept;
00122 
00123 // make_any()
00124 //
00125 // Constructs an `absl::any` of type `T` with the given arguments.
00126 template <typename T, typename... Args>
00127 any make_any(Args&&... args);
00128 
00129 // Overload of `absl::make_any()` for constructing an `absl::any` type from an
00130 // initializer list.
00131 template <typename T, typename U, typename... Args>
00132 any make_any(std::initializer_list<U> il, Args&&... args);
00133 
00134 // any_cast()
00135 //
00136 // Statically casts the value of a `const absl::any` type to the given type.
00137 // This function will throw `absl::bad_any_cast` if the stored value type of the
00138 // `absl::any` does not match the cast.
00139 //
00140 // `any_cast()` can also be used to get a reference to the internal storage iff
00141 // a reference type is passed as its `ValueType`:
00142 //
00143 // Example:
00144 //
00145 //   absl::any my_any = std::vector<int>();
00146 //   absl::any_cast<std::vector<int>&>(my_any).push_back(42);
00147 template <typename ValueType>
00148 ValueType any_cast(const any& operand);
00149 
00150 // Overload of `any_cast()` to statically cast the value of a non-const
00151 // `absl::any` type to the given type. This function will throw
00152 // `absl::bad_any_cast` if the stored value type of the `absl::any` does not
00153 // match the cast.
00154 template <typename ValueType>
00155 ValueType any_cast(any& operand);  // NOLINT(runtime/references)
00156 
00157 // Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
00158 // type. This function will throw `absl::bad_any_cast` if the stored value type
00159 // of the `absl::any` does not match the cast.
00160 template <typename ValueType>
00161 ValueType any_cast(any&& operand);
00162 
00163 // Overload of `any_cast()` to statically cast the value of a const pointer
00164 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
00165 // type of the `absl::any` does not match the cast.
00166 template <typename ValueType>
00167 const ValueType* any_cast(const any* operand) noexcept;
00168 
00169 // Overload of `any_cast()` to statically cast the value of a pointer
00170 // `absl::any` type to the given pointer type, or `nullptr` if the stored value
00171 // type of the `absl::any` does not match the cast.
00172 template <typename ValueType>
00173 ValueType* any_cast(any* operand) noexcept;
00174 
00175 // -----------------------------------------------------------------------------
00176 // absl::any
00177 // -----------------------------------------------------------------------------
00178 //
00179 // An `absl::any` object provides the facility to either store an instance of a
00180 // type, known as the "contained object", or no value. An `absl::any` is used to
00181 // store values of types that are unknown at compile time. The `absl::any`
00182 // object, when containing a value, must contain a value type; storing a
00183 // reference type is neither desired nor supported.
00184 //
00185 // An `absl::any` can only store a type that is copy-constructable; move-only
00186 // types are not allowed within an `any` object.
00187 //
00188 // Example:
00189 //
00190 //   auto a = absl::any(65);                 // Literal, copyable
00191 //   auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
00192 //   std::unique_ptr<Foo> my_foo;
00193 //   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructable
00194 //
00195 // Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
00196 // context) to remove const-volatile qualifiers (known as "cv qualifiers"),
00197 // decay functions to function pointers, etc. We essentially "decay" a given
00198 // type into its essential type.
00199 //
00200 // `absl::any` makes use of decayed types when determining the basic type `T` of
00201 // the value to store in the any's contained object. In the documentation below,
00202 // we explicitly denote this by using the phrase "a decayed type of `T`".
00203 //
00204 // Example:
00205 //
00206 //   const int a = 4;
00207 //   absl::any foo(a);  // Decay ensures we store an "int", not a "const int&".
00208 //
00209 //   void my_function() {}
00210 //   absl::any bar(my_function);  // Decay ensures we store a function pointer.
00211 //
00212 // `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
00213 // and is designed to be a drop-in replacement for code compliant with C++17.
00214 class any {
00215  private:
00216   template <typename T>
00217   struct IsInPlaceType;
00218 
00219  public:
00220   // Constructors
00221 
00222   // Constructs an empty `absl::any` object (`any::has_value()` will return
00223   // `false`).
00224   constexpr any() noexcept;
00225 
00226   // Copy constructs an `absl::any` object with a "contained object" of the
00227   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
00228   // `false`.
00229   any(const any& other)
00230       : obj_(other.has_value() ? other.obj_->Clone()
00231                                : std::unique_ptr<ObjInterface>()) {}
00232 
00233   // Move constructs an `absl::any` object with a "contained object" of the
00234   // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
00235   // `false`).
00236   any(any&& other) noexcept = default;
00237 
00238   // Constructs an `absl::any` object with a "contained object" of the decayed
00239   // type of `T`, which is initialized via `std::forward<T>(value)`.
00240   //
00241   // This constructor will not participate in overload resolution if the
00242   // decayed type of `T` is not copy-constructible.
00243   template <
00244       typename T, typename VT = absl::decay_t<T>,
00245       absl::enable_if_t<!absl::disjunction<
00246           std::is_same<any, VT>, IsInPlaceType<VT>,
00247           absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr>
00248   any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
00249 
00250   // Constructs an `absl::any` object with a "contained object" of the decayed
00251   // type of `T`, which is initialized via `std::forward<T>(value)`.
00252   template <typename T, typename... Args, typename VT = absl::decay_t<T>,
00253             absl::enable_if_t<absl::conjunction<
00254                 std::is_copy_constructible<VT>,
00255                 std::is_constructible<VT, Args...>>::value>* = nullptr>
00256   explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
00257       : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
00258 
00259   // Constructs an `absl::any` object with a "contained object" of the passed
00260   // type `VT` as a decayed type of `T`. `VT` is initialized as if
00261   // direct-non-list-initializing an object of type `VT` with the arguments
00262   // `initializer_list, std::forward<Args>(args)...`.
00263   template <
00264       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
00265       absl::enable_if_t<
00266           absl::conjunction<std::is_copy_constructible<VT>,
00267                             std::is_constructible<VT, std::initializer_list<U>&,
00268                                                   Args...>>::value>* = nullptr>
00269   explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
00270                Args&&... args)
00271       : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
00272 
00273   // Assignment operators
00274 
00275   // Copy assigns an `absl::any` object with a "contained object" of the
00276   // passed type.
00277   any& operator=(const any& rhs) {
00278     any(rhs).swap(*this);
00279     return *this;
00280   }
00281 
00282   // Move assigns an `absl::any` object with a "contained object" of the
00283   // passed type. `rhs` is left in a valid but otherwise unspecified state.
00284   any& operator=(any&& rhs) noexcept {
00285     any(std::move(rhs)).swap(*this);
00286     return *this;
00287   }
00288 
00289   // Assigns an `absl::any` object with a "contained object" of the passed type.
00290   template <typename T, typename VT = absl::decay_t<T>,
00291             absl::enable_if_t<absl::conjunction<
00292                 absl::negation<std::is_same<VT, any>>,
00293                 std::is_copy_constructible<VT>>::value>* = nullptr>
00294   any& operator=(T&& rhs) {
00295     any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
00296     tmp.swap(*this);
00297     return *this;
00298   }
00299 
00300   // Modifiers
00301 
00302   // any::emplace()
00303   //
00304   // Emplaces a value within an `absl::any` object by calling `any::reset()`,
00305   // initializing the contained value as if direct-non-list-initializing an
00306   // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
00307   // returning a reference to the new contained value.
00308   //
00309   // Note: If an exception is thrown during the call to `VT`'s constructor,
00310   // `*this` does not contain a value, and any previously contained value has
00311   // been destroyed.
00312   template <
00313       typename T, typename... Args, typename VT = absl::decay_t<T>,
00314       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
00315                         std::is_constructible<VT, Args...>::value>* = nullptr>
00316   VT& emplace(Args&&... args) {
00317     reset();  // NOTE: reset() is required here even in the world of exceptions.
00318     Obj<VT>* const object_ptr =
00319         new Obj<VT>(in_place, std::forward<Args>(args)...);
00320     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
00321     return object_ptr->value;
00322   }
00323 
00324   // Overload of `any::emplace()` to emplace a value within an `absl::any`
00325   // object by calling `any::reset()`, initializing the contained value as if
00326   // direct-non-list-initializing an object of type `VT` with the arguments
00327   // `initializer_list, std::forward<Args>(args)...`, and returning a reference
00328   // to the new contained value.
00329   //
00330   // Note: If an exception is thrown during the call to `VT`'s constructor,
00331   // `*this` does not contain a value, and any previously contained value has
00332   // been destroyed. The function shall not participate in overload resolution
00333   // unless `is_copy_constructible_v<VT>` is `true` and
00334   // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
00335   template <
00336       typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
00337       absl::enable_if_t<std::is_copy_constructible<VT>::value &&
00338                         std::is_constructible<VT, std::initializer_list<U>&,
00339                                               Args...>::value>* = nullptr>
00340   VT& emplace(std::initializer_list<U> ilist, Args&&... args) {
00341     reset();  // NOTE: reset() is required here even in the world of exceptions.
00342     Obj<VT>* const object_ptr =
00343         new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
00344     obj_ = std::unique_ptr<ObjInterface>(object_ptr);
00345     return object_ptr->value;
00346   }
00347 
00348   // any::reset()
00349   //
00350   // Resets the state of the `absl::any` object, destroying the contained object
00351   // if present.
00352   void reset() noexcept { obj_ = nullptr; }
00353 
00354   // any::swap()
00355   //
00356   // Swaps the passed value and the value of this `absl::any` object.
00357   void swap(any& other) noexcept { obj_.swap(other.obj_); }
00358 
00359   // Observers
00360 
00361   // any::has_value()
00362   //
00363   // Returns `true` if the `any` object has a contained value, otherwise
00364   // returns `false`.
00365   bool has_value() const noexcept { return obj_ != nullptr; }
00366 
00367 #if ABSL_ANY_DETAIL_HAS_RTTI
00368   // Returns: typeid(T) if *this has a contained object of type T, otherwise
00369   // typeid(void).
00370   const std::type_info& type() const noexcept {
00371     if (has_value()) {
00372       return obj_->Type();
00373     }
00374 
00375     return typeid(void);
00376   }
00377 #endif  // ABSL_ANY_DETAIL_HAS_RTTI
00378 
00379  private:
00380   // Tagged type-erased abstraction for holding a cloneable object.
00381   class ObjInterface {
00382    public:
00383     virtual ~ObjInterface() = default;
00384     virtual std::unique_ptr<ObjInterface> Clone() const = 0;
00385     virtual const void* ObjTypeId() const noexcept = 0;
00386 #if ABSL_ANY_DETAIL_HAS_RTTI
00387     virtual const std::type_info& Type() const noexcept = 0;
00388 #endif  // ABSL_ANY_DETAIL_HAS_RTTI
00389   };
00390 
00391   // Hold a value of some queryable type, with an ability to Clone it.
00392   template <typename T>
00393   class Obj : public ObjInterface {
00394    public:
00395     template <typename... Args>
00396     explicit Obj(in_place_t /*tag*/, Args&&... args)
00397         : value(std::forward<Args>(args)...) {}
00398 
00399     std::unique_ptr<ObjInterface> Clone() const final {
00400       return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
00401     }
00402 
00403     const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
00404 
00405 #if ABSL_ANY_DETAIL_HAS_RTTI
00406     const std::type_info& Type() const noexcept final { return typeid(T); }
00407 #endif  // ABSL_ANY_DETAIL_HAS_RTTI
00408 
00409     T value;
00410   };
00411 
00412   std::unique_ptr<ObjInterface> CloneObj() const {
00413     if (!obj_) return nullptr;
00414     return obj_->Clone();
00415   }
00416 
00417   template <typename T>
00418   constexpr static const void* IdForType() {
00419     // Note: This type dance is to make the behavior consistent with typeid.
00420     using NormalizedType =
00421         typename std::remove_cv<typename std::remove_reference<T>::type>::type;
00422 
00423     return any_internal::FastTypeId<NormalizedType>();
00424   }
00425 
00426   const void* GetObjTypeId() const {
00427     return obj_ ? obj_->ObjTypeId() : any_internal::FastTypeId<void>();
00428   }
00429 
00430   // `absl::any` nonmember functions //
00431 
00432   // Description at the declaration site (top of file).
00433   template <typename ValueType>
00434   friend ValueType any_cast(const any& operand);
00435 
00436   // Description at the declaration site (top of file).
00437   template <typename ValueType>
00438   friend ValueType any_cast(any& operand);  // NOLINT(runtime/references)
00439 
00440   // Description at the declaration site (top of file).
00441   template <typename T>
00442   friend const T* any_cast(const any* operand) noexcept;
00443 
00444   // Description at the declaration site (top of file).
00445   template <typename T>
00446   friend T* any_cast(any* operand) noexcept;
00447 
00448   std::unique_ptr<ObjInterface> obj_;
00449 };
00450 
00451 // -----------------------------------------------------------------------------
00452 // Implementation Details
00453 // -----------------------------------------------------------------------------
00454 
00455 constexpr any::any() noexcept = default;
00456 
00457 template <typename T>
00458 struct any::IsInPlaceType : std::false_type {};
00459 
00460 template <typename T>
00461 struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
00462 
00463 inline void swap(any& x, any& y) noexcept { x.swap(y); }
00464 
00465 // Description at the declaration site (top of file).
00466 template <typename T, typename... Args>
00467 any make_any(Args&&... args) {
00468   return any(in_place_type_t<T>(), std::forward<Args>(args)...);
00469 }
00470 
00471 // Description at the declaration site (top of file).
00472 template <typename T, typename U, typename... Args>
00473 any make_any(std::initializer_list<U> il, Args&&... args) {
00474   return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
00475 }
00476 
00477 // Description at the declaration site (top of file).
00478 template <typename ValueType>
00479 ValueType any_cast(const any& operand) {
00480   using U = typename std::remove_cv<
00481       typename std::remove_reference<ValueType>::type>::type;
00482   static_assert(std::is_constructible<ValueType, const U&>::value,
00483                 "Invalid ValueType");
00484   auto* const result = (any_cast<U>)(&operand);
00485   if (result == nullptr) {
00486     any_internal::ThrowBadAnyCast();
00487   }
00488   return static_cast<ValueType>(*result);
00489 }
00490 
00491 // Description at the declaration site (top of file).
00492 template <typename ValueType>
00493 ValueType any_cast(any& operand) {  // NOLINT(runtime/references)
00494   using U = typename std::remove_cv<
00495       typename std::remove_reference<ValueType>::type>::type;
00496   static_assert(std::is_constructible<ValueType, U&>::value,
00497                 "Invalid ValueType");
00498   auto* result = (any_cast<U>)(&operand);
00499   if (result == nullptr) {
00500     any_internal::ThrowBadAnyCast();
00501   }
00502   return static_cast<ValueType>(*result);
00503 }
00504 
00505 // Description at the declaration site (top of file).
00506 template <typename ValueType>
00507 ValueType any_cast(any&& operand) {
00508   using U = typename std::remove_cv<
00509       typename std::remove_reference<ValueType>::type>::type;
00510   static_assert(std::is_constructible<ValueType, U>::value,
00511                 "Invalid ValueType");
00512   return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
00513 }
00514 
00515 // Description at the declaration site (top of file).
00516 template <typename T>
00517 const T* any_cast(const any* operand) noexcept {
00518   return operand && operand->GetObjTypeId() == any::IdForType<T>()
00519              ? std::addressof(
00520                    static_cast<const any::Obj<T>*>(operand->obj_.get())->value)
00521              : nullptr;
00522 }
00523 
00524 // Description at the declaration site (top of file).
00525 template <typename T>
00526 T* any_cast(any* operand) noexcept {
00527   return operand && operand->GetObjTypeId() == any::IdForType<T>()
00528              ? std::addressof(
00529                    static_cast<any::Obj<T>*>(operand->obj_.get())->value)
00530              : nullptr;
00531 }
00532 
00533 }  // namespace absl
00534 
00535 #undef ABSL_ANY_DETAIL_HAS_RTTI
00536 
00537 #endif  // ABSL_HAVE_STD_ANY
00538 
00539 #endif  // ABSL_TYPES_ANY_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14