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