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