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