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 17 namespace std { 18 namespace experimental { 19 inline 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 92 class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast 93 { 94 public: 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 102 void __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 112 class any; 113 114 template <class _ValueType> 115 typename add_pointer<typename add_const<_ValueType>::type>::type 116 _LIBCPP_INLINE_VISIBILITY 117 any_cast(any const *) _NOEXCEPT; 118 119 template <class _ValueType> 120 typename add_pointer<_ValueType>::type 121 _LIBCPP_INLINE_VISIBILITY 122 any_cast(any *) _NOEXCEPT; 123 124 namespace __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 167 class any 168 { 169 public: 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 250 private: 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 292 namespace __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 464 template <class _ValueType, class> 465 any::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 474 template <class _ValueType, class> 475 any & 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 484 inline 485 void 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 503 inline _LIBCPP_INLINE_VISIBILITY 504 void swap(any & __lhs, any & __rhs) _NOEXCEPT 505 { 506 __lhs.swap(__rhs); 507 } 508 509 template <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 525 template <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 540 template <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 555 template <class _ValueType> 556 inline 557 typename add_pointer<typename add_const<_ValueType>::type>::type 558 any_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 565 template <class _ValueType> 566 typename add_pointer<_ValueType>::type 567 any_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