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