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