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 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 93namespace std { 94class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast 95{ 96public: 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 106void __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 116class _LIBCPP_TEMPLATE_VIS any; 117 118template <class _ValueType> 119_LIBCPP_INLINE_VISIBILITY 120add_pointer_t<add_const_t<_ValueType>> 121any_cast(any const *) _NOEXCEPT; 122 123template <class _ValueType> 124_LIBCPP_INLINE_VISIBILITY 125add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT; 126 127namespace __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 179class _LIBCPP_TEMPLATE_VIS any 180{ 181public: 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 294private: 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 338namespace __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 496template <class _ValueType, class _Tp, class> 497any::any(_ValueType && __v) : __h(nullptr) 498{ 499 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); 500} 501 502template <class _ValueType, class ..._Args, class _Tp, class> 503any::any(in_place_type_t<_ValueType>, _Args&&... __args) { 504 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 505}; 506 507template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 508any::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 512template <class _ValueType, class, class> 513inline _LIBCPP_INLINE_VISIBILITY 514any & any::operator=(_ValueType && __v) 515{ 516 any(_VSTD::forward<_ValueType>(__v)).swap(*this); 517 return *this; 518} 519 520template <class _ValueType, class ..._Args, class _Tp, class> 521inline _LIBCPP_INLINE_VISIBILITY 522void any::emplace(_Args&&... __args) { 523 reset(); 524 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 525} 526 527template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 528inline _LIBCPP_INLINE_VISIBILITY 529void any::emplace(initializer_list<_Up> __il, _Args&&... __args) { 530 reset(); 531 __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 532} 533 534inline _LIBCPP_INLINE_VISIBILITY 535void 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 555inline _LIBCPP_INLINE_VISIBILITY 556void swap(any & __lhs, any & __rhs) _NOEXCEPT 557{ 558 __lhs.swap(__rhs); 559} 560 561template <class _Tp, class ..._Args> 562inline _LIBCPP_INLINE_VISIBILITY 563any make_any(_Args&&... __args) { 564 return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...); 565} 566 567template <class _Tp, class _Up, class ..._Args> 568inline _LIBCPP_INLINE_VISIBILITY 569any make_any(initializer_list<_Up> __il, _Args&&... __args) { 570 return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...); 571} 572 573template <class _ValueType> 574inline _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 587template <class _ValueType> 588inline _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 601template <class _ValueType> 602inline _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 615template <class _ValueType> 616inline _LIBCPP_INLINE_VISIBILITY 617add_pointer_t<add_const_t<_ValueType>> 618any_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 625template <class _RetType> 626inline _LIBCPP_INLINE_VISIBILITY 627_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { 628 return static_cast<_RetType>(__p); 629} 630 631template <class _RetType> 632inline _LIBCPP_INLINE_VISIBILITY 633_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { 634 return nullptr; 635} 636 637template <class _ValueType> 638add_pointer_t<_ValueType> 639any_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