1 // -*- C++ -*- 2 //===------------------------------ any -----------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #ifndef _LIBCPP_ANY 12 #define _LIBCPP_ANY 13 14 /* 15 any synopsis 16 17 namespace std { 18 19 class bad_any_cast : public bad_cast 20 { 21 public: 22 virtual const char* what() const noexcept; 23 }; 24 25 class any 26 { 27 public: 28 29 // 6.3.1 any construct/destruct 30 any() noexcept; 31 32 any(const any& other); 33 any(any&& other) noexcept; 34 35 template <class ValueType> 36 any(ValueType&& value); 37 38 ~any(); 39 40 // 6.3.2 any assignments 41 any& operator=(const any& rhs); 42 any& operator=(any&& rhs) noexcept; 43 44 template <class ValueType> 45 any& operator=(ValueType&& rhs); 46 47 // 6.3.3 any modifiers 48 template <class ValueType, class... Args> 49 decay_t<ValueType>& emplace(Args&&... args); 50 template <class ValueType, class U, class... Args> 51 decay_t<ValueType>& emplace(initializer_list<U>, Args&&...); 52 void reset() noexcept; 53 void swap(any& rhs) noexcept; 54 55 // 6.3.4 any observers 56 bool has_value() const noexcept; 57 const type_info& type() const noexcept; 58 }; 59 60 // 6.4 Non-member functions 61 void swap(any& x, any& y) noexcept; 62 63 template <class T, class ...Args> 64 any make_any(Args&& ...args); 65 template <class T, class U, class ...Args> 66 any make_any(initializer_list<U>, Args&& ...args); 67 68 template<class ValueType> 69 ValueType any_cast(const any& operand); 70 template<class ValueType> 71 ValueType any_cast(any& operand); 72 template<class ValueType> 73 ValueType any_cast(any&& operand); 74 75 template<class ValueType> 76 const ValueType* any_cast(const any* operand) noexcept; 77 template<class ValueType> 78 ValueType* any_cast(any* operand) noexcept; 79 80 } // namespace std 81 82 */ 83 84 #include <experimental/__config> 85 #include <memory> 86 #include <new> 87 #include <typeinfo> 88 #include <type_traits> 89 #include <cstdlib> 90 91 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 92 #pragma GCC system_header 93 #endif 94 95 namespace std { 96 class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast 97 { 98 public: 99 virtual const char* what() const _NOEXCEPT; 100 }; 101 } // namespace std 102 103 _LIBCPP_BEGIN_NAMESPACE_STD 104 105 #if _LIBCPP_STD_VER > 14 106 107 _LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE 108 void __throw_bad_any_cast() 109 { 110 #ifndef _LIBCPP_NO_EXCEPTIONS 111 throw bad_any_cast(); 112 #else 113 _VSTD::abort(); 114 #endif 115 } 116 117 // Forward declarations 118 class _LIBCPP_TEMPLATE_VIS any; 119 120 template <class _ValueType> 121 _LIBCPP_INLINE_VISIBILITY 122 add_pointer_t<add_const_t<_ValueType>> 123 any_cast(any const *) _NOEXCEPT; 124 125 template <class _ValueType> 126 _LIBCPP_INLINE_VISIBILITY 127 add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT; 128 129 namespace __any_imp 130 { 131 using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>; 132 133 template <class _Tp> 134 using _IsSmallObject = integral_constant<bool 135 , sizeof(_Tp) <= sizeof(_Buffer) 136 && alignment_of<_Buffer>::value 137 % alignment_of<_Tp>::value == 0 138 && is_nothrow_move_constructible<_Tp>::value 139 >; 140 141 enum class _Action { 142 _Destroy, 143 _Copy, 144 _Move, 145 _Get, 146 _TypeInfo 147 }; 148 149 template <class _Tp> struct _SmallHandler; 150 template <class _Tp> struct _LargeHandler; 151 152 template <class _Tp> 153 struct _LIBCPP_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; }; 154 template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id; 155 156 template <class _Tp> 157 inline _LIBCPP_INLINE_VISIBILITY 158 constexpr const void* __get_fallback_typeid() { 159 return &__unique_typeinfo<decay_t<_Tp>>::__id; 160 } 161 162 template <class _Tp> 163 inline _LIBCPP_INLINE_VISIBILITY 164 bool __compare_typeid(type_info const* __id, const void* __fallback_id) 165 { 166 #if !defined(_LIBCPP_NO_RTTI) 167 if (__id && *__id == typeid(_Tp)) 168 return true; 169 #endif 170 if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>()) 171 return true; 172 return false; 173 } 174 175 template <class _Tp> 176 using _Handler = conditional_t< 177 _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>; 178 179 } // namespace __any_imp 180 181 class _LIBCPP_TEMPLATE_VIS any 182 { 183 public: 184 // construct/destruct 185 _LIBCPP_INLINE_VISIBILITY 186 constexpr any() _NOEXCEPT : __h(nullptr) {} 187 188 _LIBCPP_INLINE_VISIBILITY 189 any(any const & __other) : __h(nullptr) 190 { 191 if (__other.__h) __other.__call(_Action::_Copy, this); 192 } 193 194 _LIBCPP_INLINE_VISIBILITY 195 any(any && __other) _NOEXCEPT : __h(nullptr) 196 { 197 if (__other.__h) __other.__call(_Action::_Move, this); 198 } 199 200 template < 201 class _ValueType 202 , class _Tp = decay_t<_ValueType> 203 , class = enable_if_t< 204 !is_same<_Tp, any>::value && 205 !__is_inplace_type<_ValueType>::value && 206 is_copy_constructible<_Tp>::value> 207 > 208 _LIBCPP_INLINE_VISIBILITY 209 any(_ValueType && __value); 210 211 template <class _ValueType, class ..._Args, 212 class _Tp = decay_t<_ValueType>, 213 class = enable_if_t< 214 is_constructible<_Tp, _Args...>::value && 215 is_copy_constructible<_Tp>::value 216 > 217 > 218 _LIBCPP_INLINE_VISIBILITY 219 explicit any(in_place_type_t<_ValueType>, _Args&&... __args); 220 221 template <class _ValueType, class _Up, class ..._Args, 222 class _Tp = decay_t<_ValueType>, 223 class = enable_if_t< 224 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && 225 is_copy_constructible<_Tp>::value> 226 > 227 _LIBCPP_INLINE_VISIBILITY 228 explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args); 229 230 _LIBCPP_INLINE_VISIBILITY 231 ~any() { this->reset(); } 232 233 // assignments 234 _LIBCPP_INLINE_VISIBILITY 235 any & operator=(any const & __rhs) { 236 any(__rhs).swap(*this); 237 return *this; 238 } 239 240 _LIBCPP_INLINE_VISIBILITY 241 any & operator=(any && __rhs) _NOEXCEPT { 242 any(_VSTD::move(__rhs)).swap(*this); 243 return *this; 244 } 245 246 template < 247 class _ValueType 248 , class _Tp = decay_t<_ValueType> 249 , class = enable_if_t< 250 !is_same<_Tp, any>::value 251 && is_copy_constructible<_Tp>::value> 252 > 253 _LIBCPP_INLINE_VISIBILITY 254 any & operator=(_ValueType && __rhs); 255 256 template <class _ValueType, class ..._Args, 257 class _Tp = decay_t<_ValueType>, 258 class = enable_if_t< 259 is_constructible<_Tp, _Args...>::value && 260 is_copy_constructible<_Tp>::value> 261 > 262 _LIBCPP_INLINE_VISIBILITY 263 _Tp& emplace(_Args&&... args); 264 265 template <class _ValueType, class _Up, class ..._Args, 266 class _Tp = decay_t<_ValueType>, 267 class = enable_if_t< 268 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && 269 is_copy_constructible<_Tp>::value> 270 > 271 _LIBCPP_INLINE_VISIBILITY 272 _Tp& emplace(initializer_list<_Up>, _Args&&...); 273 274 // 6.3.3 any modifiers 275 _LIBCPP_INLINE_VISIBILITY 276 void reset() _NOEXCEPT { if (__h) this->__call(_Action::_Destroy); } 277 278 _LIBCPP_INLINE_VISIBILITY 279 void swap(any & __rhs) _NOEXCEPT; 280 281 // 6.3.4 any observers 282 _LIBCPP_INLINE_VISIBILITY 283 bool has_value() const _NOEXCEPT { return __h != nullptr; } 284 285 #if !defined(_LIBCPP_NO_RTTI) 286 _LIBCPP_INLINE_VISIBILITY 287 const type_info & type() const _NOEXCEPT { 288 if (__h) { 289 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo)); 290 } else { 291 return typeid(void); 292 } 293 } 294 #endif 295 296 private: 297 typedef __any_imp::_Action _Action; 298 using _HandleFuncPtr = void* (*)(_Action, any const *, any *, const type_info *, 299 const void* __fallback_info); 300 301 union _Storage { 302 constexpr _Storage() : __ptr(nullptr) {} 303 void * __ptr; 304 __any_imp::_Buffer __buf; 305 }; 306 307 _LIBCPP_ALWAYS_INLINE 308 void * __call(_Action __a, any * __other = nullptr, 309 type_info const * __info = nullptr, 310 const void* __fallback_info = nullptr) const 311 { 312 return __h(__a, this, __other, __info, __fallback_info); 313 } 314 315 _LIBCPP_ALWAYS_INLINE 316 void * __call(_Action __a, any * __other = nullptr, 317 type_info const * __info = nullptr, 318 const void* __fallback_info = nullptr) 319 { 320 return __h(__a, this, __other, __info, __fallback_info); 321 } 322 323 template <class> 324 friend struct __any_imp::_SmallHandler; 325 template <class> 326 friend struct __any_imp::_LargeHandler; 327 328 template <class _ValueType> 329 friend add_pointer_t<add_const_t<_ValueType>> 330 any_cast(any const *) _NOEXCEPT; 331 332 template <class _ValueType> 333 friend add_pointer_t<_ValueType> 334 any_cast(any *) _NOEXCEPT; 335 336 _HandleFuncPtr __h = nullptr; 337 _Storage __s; 338 }; 339 340 namespace __any_imp 341 { 342 template <class _Tp> 343 struct _LIBCPP_TEMPLATE_VIS _SmallHandler 344 { 345 _LIBCPP_INLINE_VISIBILITY 346 static void* __handle(_Action __act, any const * __this, any * __other, 347 type_info const * __info, const void* __fallback_info) 348 { 349 switch (__act) 350 { 351 case _Action::_Destroy: 352 __destroy(const_cast<any &>(*__this)); 353 return nullptr; 354 case _Action::_Copy: 355 __copy(*__this, *__other); 356 return nullptr; 357 case _Action::_Move: 358 __move(const_cast<any &>(*__this), *__other); 359 return nullptr; 360 case _Action::_Get: 361 return __get(const_cast<any &>(*__this), __info, __fallback_info); 362 case _Action::_TypeInfo: 363 return __type_info(); 364 } 365 } 366 367 template <class ..._Args> 368 _LIBCPP_INLINE_VISIBILITY 369 static _Tp& __create(any & __dest, _Args&&... __args) { 370 _Tp* __ret = ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...); 371 __dest.__h = &_SmallHandler::__handle; 372 return *__ret; 373 } 374 375 private: 376 _LIBCPP_INLINE_VISIBILITY 377 static void __destroy(any & __this) { 378 _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf)); 379 __value.~_Tp(); 380 __this.__h = nullptr; 381 } 382 383 _LIBCPP_INLINE_VISIBILITY 384 static void __copy(any const & __this, any & __dest) { 385 _SmallHandler::__create(__dest, *static_cast<_Tp const *>( 386 static_cast<void const *>(&__this.__s.__buf))); 387 } 388 389 _LIBCPP_INLINE_VISIBILITY 390 static void __move(any & __this, any & __dest) { 391 _SmallHandler::__create(__dest, _VSTD::move( 392 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf)))); 393 __destroy(__this); 394 } 395 396 _LIBCPP_INLINE_VISIBILITY 397 static void* __get(any & __this, 398 type_info const * __info, 399 const void* __fallback_id) 400 { 401 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id)) 402 return static_cast<void*>(&__this.__s.__buf); 403 return nullptr; 404 } 405 406 _LIBCPP_INLINE_VISIBILITY 407 static void* __type_info() 408 { 409 #if !defined(_LIBCPP_NO_RTTI) 410 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 411 #else 412 return nullptr; 413 #endif 414 } 415 }; 416 417 template <class _Tp> 418 struct _LIBCPP_TEMPLATE_VIS _LargeHandler 419 { 420 _LIBCPP_INLINE_VISIBILITY 421 static void* __handle(_Action __act, any const * __this, 422 any * __other, type_info const * __info, 423 void const* __fallback_info) 424 { 425 switch (__act) 426 { 427 case _Action::_Destroy: 428 __destroy(const_cast<any &>(*__this)); 429 return nullptr; 430 case _Action::_Copy: 431 __copy(*__this, *__other); 432 return nullptr; 433 case _Action::_Move: 434 __move(const_cast<any &>(*__this), *__other); 435 return nullptr; 436 case _Action::_Get: 437 return __get(const_cast<any &>(*__this), __info, __fallback_info); 438 case _Action::_TypeInfo: 439 return __type_info(); 440 } 441 } 442 443 template <class ..._Args> 444 _LIBCPP_INLINE_VISIBILITY 445 static _Tp& __create(any & __dest, _Args&&... __args) { 446 typedef allocator<_Tp> _Alloc; 447 typedef __allocator_destructor<_Alloc> _Dp; 448 _Alloc __a; 449 unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); 450 _Tp* __ret = ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...); 451 __dest.__s.__ptr = __hold.release(); 452 __dest.__h = &_LargeHandler::__handle; 453 return *__ret; 454 } 455 456 private: 457 458 _LIBCPP_INLINE_VISIBILITY 459 static void __destroy(any & __this){ 460 delete static_cast<_Tp*>(__this.__s.__ptr); 461 __this.__h = nullptr; 462 } 463 464 _LIBCPP_INLINE_VISIBILITY 465 static void __copy(any const & __this, any & __dest) { 466 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr)); 467 } 468 469 _LIBCPP_INLINE_VISIBILITY 470 static void __move(any & __this, any & __dest) { 471 __dest.__s.__ptr = __this.__s.__ptr; 472 __dest.__h = &_LargeHandler::__handle; 473 __this.__h = nullptr; 474 } 475 476 _LIBCPP_INLINE_VISIBILITY 477 static void* __get(any & __this, type_info const * __info, 478 void const* __fallback_info) 479 { 480 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info)) 481 return static_cast<void*>(__this.__s.__ptr); 482 return nullptr; 483 484 } 485 486 _LIBCPP_INLINE_VISIBILITY 487 static void* __type_info() 488 { 489 #if !defined(_LIBCPP_NO_RTTI) 490 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 491 #else 492 return nullptr; 493 #endif 494 } 495 }; 496 497 } // namespace __any_imp 498 499 500 template <class _ValueType, class _Tp, class> 501 any::any(_ValueType && __v) : __h(nullptr) 502 { 503 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); 504 } 505 506 template <class _ValueType, class ..._Args, class _Tp, class> 507 any::any(in_place_type_t<_ValueType>, _Args&&... __args) { 508 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 509 }; 510 511 template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 512 any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) { 513 __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 514 } 515 516 template <class _ValueType, class, class> 517 inline _LIBCPP_INLINE_VISIBILITY 518 any & any::operator=(_ValueType && __v) 519 { 520 any(_VSTD::forward<_ValueType>(__v)).swap(*this); 521 return *this; 522 } 523 524 template <class _ValueType, class ..._Args, class _Tp, class> 525 inline _LIBCPP_INLINE_VISIBILITY 526 _Tp& any::emplace(_Args&&... __args) { 527 reset(); 528 return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 529 } 530 531 template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 532 inline _LIBCPP_INLINE_VISIBILITY 533 _Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) { 534 reset(); 535 return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 536 } 537 538 inline _LIBCPP_INLINE_VISIBILITY 539 void any::swap(any & __rhs) _NOEXCEPT 540 { 541 if (this == &__rhs) 542 return; 543 if (__h && __rhs.__h) { 544 any __tmp; 545 __rhs.__call(_Action::_Move, &__tmp); 546 this->__call(_Action::_Move, &__rhs); 547 __tmp.__call(_Action::_Move, this); 548 } 549 else if (__h) { 550 this->__call(_Action::_Move, &__rhs); 551 } 552 else if (__rhs.__h) { 553 __rhs.__call(_Action::_Move, this); 554 } 555 } 556 557 // 6.4 Non-member functions 558 559 inline _LIBCPP_INLINE_VISIBILITY 560 void swap(any & __lhs, any & __rhs) _NOEXCEPT 561 { 562 __lhs.swap(__rhs); 563 } 564 565 template <class _Tp, class ..._Args> 566 inline _LIBCPP_INLINE_VISIBILITY 567 any make_any(_Args&&... __args) { 568 return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...); 569 } 570 571 template <class _Tp, class _Up, class ..._Args> 572 inline _LIBCPP_INLINE_VISIBILITY 573 any make_any(initializer_list<_Up> __il, _Args&&... __args) { 574 return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...); 575 } 576 577 template <class _ValueType> 578 inline _LIBCPP_INLINE_VISIBILITY 579 _ValueType any_cast(any const & __v) 580 { 581 using _RawValueType = __uncvref_t<_ValueType>; 582 static_assert(is_constructible<_ValueType, _RawValueType const &>::value, 583 "ValueType is required to be a const lvalue reference " 584 "or a CopyConstructible type"); 585 auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v); 586 if (__tmp == nullptr) 587 __throw_bad_any_cast(); 588 return static_cast<_ValueType>(*__tmp); 589 } 590 591 template <class _ValueType> 592 inline _LIBCPP_INLINE_VISIBILITY 593 _ValueType any_cast(any & __v) 594 { 595 using _RawValueType = __uncvref_t<_ValueType>; 596 static_assert(is_constructible<_ValueType, _RawValueType &>::value, 597 "ValueType is required to be an lvalue reference " 598 "or a CopyConstructible type"); 599 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 600 if (__tmp == nullptr) 601 __throw_bad_any_cast(); 602 return static_cast<_ValueType>(*__tmp); 603 } 604 605 template <class _ValueType> 606 inline _LIBCPP_INLINE_VISIBILITY 607 _ValueType any_cast(any && __v) 608 { 609 using _RawValueType = __uncvref_t<_ValueType>; 610 static_assert(is_constructible<_ValueType, _RawValueType>::value, 611 "ValueType is required to be an rvalue reference " 612 "or a CopyConstructible type"); 613 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 614 if (__tmp == nullptr) 615 __throw_bad_any_cast(); 616 return static_cast<_ValueType>(_VSTD::move(*__tmp)); 617 } 618 619 template <class _ValueType> 620 inline _LIBCPP_INLINE_VISIBILITY 621 add_pointer_t<add_const_t<_ValueType>> 622 any_cast(any const * __any) _NOEXCEPT 623 { 624 static_assert(!is_reference<_ValueType>::value, 625 "_ValueType may not be a reference."); 626 return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any)); 627 } 628 629 template <class _RetType> 630 inline _LIBCPP_INLINE_VISIBILITY 631 _RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { 632 return static_cast<_RetType>(__p); 633 } 634 635 template <class _RetType> 636 inline _LIBCPP_INLINE_VISIBILITY 637 _RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { 638 return nullptr; 639 } 640 641 template <class _ValueType> 642 add_pointer_t<_ValueType> 643 any_cast(any * __any) _NOEXCEPT 644 { 645 using __any_imp::_Action; 646 static_assert(!is_reference<_ValueType>::value, 647 "_ValueType may not be a reference."); 648 typedef typename add_pointer<_ValueType>::type _ReturnType; 649 if (__any && __any->__h) { 650 void *__p = __any->__call(_Action::_Get, nullptr, 651 #if !defined(_LIBCPP_NO_RTTI) 652 &typeid(_ValueType), 653 #else 654 nullptr, 655 #endif 656 __any_imp::__get_fallback_typeid<_ValueType>()); 657 return _VSTD::__pointer_or_func_cast<_ReturnType>( 658 __p, is_function<_ValueType>{}); 659 } 660 return nullptr; 661 } 662 663 #endif // _LIBCPP_STD_VER > 14 664 665 _LIBCPP_END_NAMESPACE_STD 666 667 #endif // _LIBCPP_ANY 668