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 17namespace 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 95namespace std { 96class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast 97{ 98public: 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 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<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 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_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 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 _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 500template <class _ValueType, class _Tp, class> 501any::any(_ValueType && __v) : __h(nullptr) 502{ 503 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); 504} 505 506template <class _ValueType, class ..._Args, class _Tp, class> 507any::any(in_place_type_t<_ValueType>, _Args&&... __args) { 508 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 509}; 510 511template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 512any::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 516template <class _ValueType, class, class> 517inline _LIBCPP_INLINE_VISIBILITY 518any & any::operator=(_ValueType && __v) 519{ 520 any(_VSTD::forward<_ValueType>(__v)).swap(*this); 521 return *this; 522} 523 524template <class _ValueType, class ..._Args, class _Tp, class> 525inline _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 531template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 532inline _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 538inline _LIBCPP_INLINE_VISIBILITY 539void 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 559inline _LIBCPP_INLINE_VISIBILITY 560void swap(any & __lhs, any & __rhs) _NOEXCEPT 561{ 562 __lhs.swap(__rhs); 563} 564 565template <class _Tp, class ..._Args> 566inline _LIBCPP_INLINE_VISIBILITY 567any make_any(_Args&&... __args) { 568 return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...); 569} 570 571template <class _Tp, class _Up, class ..._Args> 572inline _LIBCPP_INLINE_VISIBILITY 573any make_any(initializer_list<_Up> __il, _Args&&... __args) { 574 return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...); 575} 576 577template <class _ValueType> 578inline _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 591template <class _ValueType> 592inline _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 605template <class _ValueType> 606inline _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 619template <class _ValueType> 620inline _LIBCPP_INLINE_VISIBILITY 621add_pointer_t<add_const_t<_ValueType>> 622any_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 629template <class _RetType> 630inline _LIBCPP_INLINE_VISIBILITY 631_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { 632 return static_cast<_RetType>(__p); 633} 634 635template <class _RetType> 636inline _LIBCPP_INLINE_VISIBILITY 637_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { 638 return nullptr; 639} 640 641template <class _ValueType> 642add_pointer_t<_ValueType> 643any_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