1// -*- C++ -*- 2//===------------------------------ any -----------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_ANY 11#define _LIBCPP_ANY 12 13/* 14 any synopsis 15 16namespace std { 17 18 class bad_any_cast : public bad_cast 19 { 20 public: 21 virtual const char* what() const noexcept; 22 }; 23 24 class any 25 { 26 public: 27 28 // 6.3.1 any construct/destruct 29 any() noexcept; 30 31 any(const any& other); 32 any(any&& other) noexcept; 33 34 template <class ValueType> 35 any(ValueType&& value); 36 37 ~any(); 38 39 // 6.3.2 any assignments 40 any& operator=(const any& rhs); 41 any& operator=(any&& rhs) noexcept; 42 43 template <class ValueType> 44 any& operator=(ValueType&& rhs); 45 46 // 6.3.3 any modifiers 47 template <class ValueType, class... Args> 48 decay_t<ValueType>& emplace(Args&&... args); 49 template <class ValueType, class U, class... Args> 50 decay_t<ValueType>& emplace(initializer_list<U>, Args&&...); 51 void reset() noexcept; 52 void swap(any& rhs) noexcept; 53 54 // 6.3.4 any observers 55 bool has_value() const noexcept; 56 const type_info& type() const noexcept; 57 }; 58 59 // 6.4 Non-member functions 60 void swap(any& x, any& y) noexcept; 61 62 template <class T, class ...Args> 63 any make_any(Args&& ...args); 64 template <class T, class U, class ...Args> 65 any make_any(initializer_list<U>, Args&& ...args); 66 67 template<class ValueType> 68 ValueType any_cast(const any& operand); 69 template<class ValueType> 70 ValueType any_cast(any& operand); 71 template<class ValueType> 72 ValueType any_cast(any&& operand); 73 74 template<class ValueType> 75 const ValueType* any_cast(const any* operand) noexcept; 76 template<class ValueType> 77 ValueType* any_cast(any* operand) noexcept; 78 79} // namespace std 80 81*/ 82 83#include <experimental/__config> 84#include <memory> 85#include <typeinfo> 86#include <type_traits> 87#include <cstdlib> 88#include <version> 89 90#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 91#pragma GCC system_header 92#endif 93 94namespace std { 95class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast 96{ 97public: 98 virtual const char* what() const _NOEXCEPT; 99}; 100} // namespace std 101 102_LIBCPP_BEGIN_NAMESPACE_STD 103 104#if _LIBCPP_STD_VER > 14 105 106_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY 107_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 108void __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 118class _LIBCPP_TEMPLATE_VIS any; 119 120template <class _ValueType> 121_LIBCPP_INLINE_VISIBILITY 122add_pointer_t<add_const_t<_ValueType>> 123any_cast(any const *) _NOEXCEPT; 124 125template <class _ValueType> 126_LIBCPP_INLINE_VISIBILITY 127add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT; 128 129namespace __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<remove_cv_t<remove_reference_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 181class _LIBCPP_TEMPLATE_VIS any 182{ 183public: 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 296private: 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_INLINE_VISIBILITY 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_INLINE_VISIBILITY 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 340namespace __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 typedef allocator<_Tp> _Alloc; 371 typedef allocator_traits<_Alloc> _ATraits; 372 _Alloc __a; 373 _Tp * __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s.__buf)); 374 _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...); 375 __dest.__h = &_SmallHandler::__handle; 376 return *__ret; 377 } 378 379 private: 380 _LIBCPP_INLINE_VISIBILITY 381 static void __destroy(any & __this) { 382 typedef allocator<_Tp> _Alloc; 383 typedef allocator_traits<_Alloc> _ATraits; 384 _Alloc __a; 385 _Tp * __p = static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf)); 386 _ATraits::destroy(__a, __p); 387 __this.__h = nullptr; 388 } 389 390 _LIBCPP_INLINE_VISIBILITY 391 static void __copy(any const & __this, any & __dest) { 392 _SmallHandler::__create(__dest, *static_cast<_Tp const *>( 393 static_cast<void const *>(&__this.__s.__buf))); 394 } 395 396 _LIBCPP_INLINE_VISIBILITY 397 static void __move(any & __this, any & __dest) { 398 _SmallHandler::__create(__dest, _VSTD::move( 399 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf)))); 400 __destroy(__this); 401 } 402 403 _LIBCPP_INLINE_VISIBILITY 404 static void* __get(any & __this, 405 type_info const * __info, 406 const void* __fallback_id) 407 { 408 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id)) 409 return static_cast<void*>(&__this.__s.__buf); 410 return nullptr; 411 } 412 413 _LIBCPP_INLINE_VISIBILITY 414 static void* __type_info() 415 { 416#if !defined(_LIBCPP_NO_RTTI) 417 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 418#else 419 return nullptr; 420#endif 421 } 422 }; 423 424 template <class _Tp> 425 struct _LIBCPP_TEMPLATE_VIS _LargeHandler 426 { 427 _LIBCPP_INLINE_VISIBILITY 428 static void* __handle(_Action __act, any const * __this, 429 any * __other, type_info const * __info, 430 void const* __fallback_info) 431 { 432 switch (__act) 433 { 434 case _Action::_Destroy: 435 __destroy(const_cast<any &>(*__this)); 436 return nullptr; 437 case _Action::_Copy: 438 __copy(*__this, *__other); 439 return nullptr; 440 case _Action::_Move: 441 __move(const_cast<any &>(*__this), *__other); 442 return nullptr; 443 case _Action::_Get: 444 return __get(const_cast<any &>(*__this), __info, __fallback_info); 445 case _Action::_TypeInfo: 446 return __type_info(); 447 } 448 } 449 450 template <class ..._Args> 451 _LIBCPP_INLINE_VISIBILITY 452 static _Tp& __create(any & __dest, _Args&&... __args) { 453 typedef allocator<_Tp> _Alloc; 454 typedef allocator_traits<_Alloc> _ATraits; 455 typedef __allocator_destructor<_Alloc> _Dp; 456 _Alloc __a; 457 unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1)); 458 _Tp * __ret = __hold.get(); 459 _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...); 460 __dest.__s.__ptr = __hold.release(); 461 __dest.__h = &_LargeHandler::__handle; 462 return *__ret; 463 } 464 465 private: 466 467 _LIBCPP_INLINE_VISIBILITY 468 static void __destroy(any & __this){ 469 typedef allocator<_Tp> _Alloc; 470 typedef allocator_traits<_Alloc> _ATraits; 471 _Alloc __a; 472 _Tp * __p = static_cast<_Tp *>(__this.__s.__ptr); 473 _ATraits::destroy(__a, __p); 474 _ATraits::deallocate(__a, __p, 1); 475 __this.__h = nullptr; 476 } 477 478 _LIBCPP_INLINE_VISIBILITY 479 static void __copy(any const & __this, any & __dest) { 480 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr)); 481 } 482 483 _LIBCPP_INLINE_VISIBILITY 484 static void __move(any & __this, any & __dest) { 485 __dest.__s.__ptr = __this.__s.__ptr; 486 __dest.__h = &_LargeHandler::__handle; 487 __this.__h = nullptr; 488 } 489 490 _LIBCPP_INLINE_VISIBILITY 491 static void* __get(any & __this, type_info const * __info, 492 void const* __fallback_info) 493 { 494 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info)) 495 return static_cast<void*>(__this.__s.__ptr); 496 return nullptr; 497 498 } 499 500 _LIBCPP_INLINE_VISIBILITY 501 static void* __type_info() 502 { 503#if !defined(_LIBCPP_NO_RTTI) 504 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 505#else 506 return nullptr; 507#endif 508 } 509 }; 510 511} // namespace __any_imp 512 513 514template <class _ValueType, class _Tp, class> 515any::any(_ValueType && __v) : __h(nullptr) 516{ 517 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); 518} 519 520template <class _ValueType, class ..._Args, class _Tp, class> 521any::any(in_place_type_t<_ValueType>, _Args&&... __args) { 522 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 523} 524 525template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 526any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) { 527 __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 528} 529 530template <class _ValueType, class, class> 531inline _LIBCPP_INLINE_VISIBILITY 532any & any::operator=(_ValueType && __v) 533{ 534 any(_VSTD::forward<_ValueType>(__v)).swap(*this); 535 return *this; 536} 537 538template <class _ValueType, class ..._Args, class _Tp, class> 539inline _LIBCPP_INLINE_VISIBILITY 540_Tp& any::emplace(_Args&&... __args) { 541 reset(); 542 return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 543} 544 545template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 546inline _LIBCPP_INLINE_VISIBILITY 547_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) { 548 reset(); 549 return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 550} 551 552inline _LIBCPP_INLINE_VISIBILITY 553void any::swap(any & __rhs) _NOEXCEPT 554{ 555 if (this == &__rhs) 556 return; 557 if (__h && __rhs.__h) { 558 any __tmp; 559 __rhs.__call(_Action::_Move, &__tmp); 560 this->__call(_Action::_Move, &__rhs); 561 __tmp.__call(_Action::_Move, this); 562 } 563 else if (__h) { 564 this->__call(_Action::_Move, &__rhs); 565 } 566 else if (__rhs.__h) { 567 __rhs.__call(_Action::_Move, this); 568 } 569} 570 571// 6.4 Non-member functions 572 573inline _LIBCPP_INLINE_VISIBILITY 574void swap(any & __lhs, any & __rhs) _NOEXCEPT 575{ 576 __lhs.swap(__rhs); 577} 578 579template <class _Tp, class ..._Args> 580inline _LIBCPP_INLINE_VISIBILITY 581any make_any(_Args&&... __args) { 582 return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...); 583} 584 585template <class _Tp, class _Up, class ..._Args> 586inline _LIBCPP_INLINE_VISIBILITY 587any make_any(initializer_list<_Up> __il, _Args&&... __args) { 588 return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...); 589} 590 591template <class _ValueType> 592inline _LIBCPP_INLINE_VISIBILITY 593_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 594_ValueType any_cast(any const & __v) 595{ 596 using _RawValueType = __uncvref_t<_ValueType>; 597 static_assert(is_constructible<_ValueType, _RawValueType const &>::value, 598 "ValueType is required to be a const lvalue reference " 599 "or a CopyConstructible type"); 600 auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v); 601 if (__tmp == nullptr) 602 __throw_bad_any_cast(); 603 return static_cast<_ValueType>(*__tmp); 604} 605 606template <class _ValueType> 607inline _LIBCPP_INLINE_VISIBILITY 608_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 609_ValueType any_cast(any & __v) 610{ 611 using _RawValueType = __uncvref_t<_ValueType>; 612 static_assert(is_constructible<_ValueType, _RawValueType &>::value, 613 "ValueType is required to be an lvalue reference " 614 "or a CopyConstructible type"); 615 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 616 if (__tmp == nullptr) 617 __throw_bad_any_cast(); 618 return static_cast<_ValueType>(*__tmp); 619} 620 621template <class _ValueType> 622inline _LIBCPP_INLINE_VISIBILITY 623_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 624_ValueType any_cast(any && __v) 625{ 626 using _RawValueType = __uncvref_t<_ValueType>; 627 static_assert(is_constructible<_ValueType, _RawValueType>::value, 628 "ValueType is required to be an rvalue reference " 629 "or a CopyConstructible type"); 630 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 631 if (__tmp == nullptr) 632 __throw_bad_any_cast(); 633 return static_cast<_ValueType>(_VSTD::move(*__tmp)); 634} 635 636template <class _ValueType> 637inline _LIBCPP_INLINE_VISIBILITY 638add_pointer_t<add_const_t<_ValueType>> 639any_cast(any const * __any) _NOEXCEPT 640{ 641 static_assert(!is_reference<_ValueType>::value, 642 "_ValueType may not be a reference."); 643 return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any)); 644} 645 646template <class _RetType> 647inline _LIBCPP_INLINE_VISIBILITY 648_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { 649 return static_cast<_RetType>(__p); 650} 651 652template <class _RetType> 653inline _LIBCPP_INLINE_VISIBILITY 654_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { 655 return nullptr; 656} 657 658template <class _ValueType> 659add_pointer_t<_ValueType> 660any_cast(any * __any) _NOEXCEPT 661{ 662 using __any_imp::_Action; 663 static_assert(!is_reference<_ValueType>::value, 664 "_ValueType may not be a reference."); 665 typedef typename add_pointer<_ValueType>::type _ReturnType; 666 if (__any && __any->__h) { 667 void *__p = __any->__call(_Action::_Get, nullptr, 668#if !defined(_LIBCPP_NO_RTTI) 669 &typeid(_ValueType), 670#else 671 nullptr, 672#endif 673 __any_imp::__get_fallback_typeid<_ValueType>()); 674 return _VSTD::__pointer_or_func_cast<_ReturnType>( 675 __p, is_function<_ValueType>{}); 676 } 677 return nullptr; 678} 679 680#endif // _LIBCPP_STD_VER > 14 681 682_LIBCPP_END_NAMESPACE_STD 683 684#endif // _LIBCPP_ANY 685