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 bad_any_cast : public bad_cast 93 { 94 public: 95 //TODO(EricWF) Enable or delete these. 96 //bad_any_cast() _NOEXCEPT; 97 //virtual ~bad_any_cast() _NOEXCEPT; 98 virtual const char* what() const _NOEXCEPT; 99 }; 100 101 #if _LIBCPP_STD_VER > 11 // C++ > 11 102 103 _LIBCPP_NORETURN _LIBCPP_INLINE_VISIBILITY 104 inline void __throw_bad_any_cast() 105 { 106 #ifndef _LIBCPP_NO_EXCEPTIONS 107 throw bad_any_cast(); 108 #else 109 _VSTD::abort(); 110 #endif 111 } 112 113 // Forward declarations 114 class any; 115 116 template <class _ValueType> 117 typename add_pointer<typename add_const<_ValueType>::type>::type 118 any_cast(any const *) _NOEXCEPT; 119 120 template <class _ValueType> 121 typename add_pointer<_ValueType>::type 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 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 any & operator=(_ValueType && __rhs); 218 219 // 6.3.3 any modifiers 220 _LIBCPP_INLINE_VISIBILITY 221 void clear() _NOEXCEPT 222 { 223 if (__h) this->__call(_Action::_Destroy); 224 } 225 226 void swap(any & __rhs) _NOEXCEPT; 227 228 // 6.3.4 any observers 229 _LIBCPP_INLINE_VISIBILITY 230 bool empty() const _NOEXCEPT 231 { 232 return __h == nullptr; 233 } 234 235 #if !defined(_LIBCPP_NO_RTTI) 236 _LIBCPP_INLINE_VISIBILITY 237 const type_info & type() const _NOEXCEPT 238 { 239 if (__h) { 240 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo)); 241 } else { 242 return typeid(void); 243 } 244 } 245 #endif 246 247 private: 248 typedef __any_imp::_Action _Action; 249 250 typedef void* (*_HandleFuncPtr)(_Action, any const *, any *, const type_info *); 251 252 union _Storage 253 { 254 void * __ptr; 255 __any_imp::_Buffer __buf; 256 }; 257 258 _LIBCPP_ALWAYS_INLINE 259 void * __call(_Action __a, any * __other = nullptr, 260 type_info const * __info = nullptr) const 261 { 262 return __h(__a, this, __other, __info); 263 } 264 265 _LIBCPP_ALWAYS_INLINE 266 void * __call(_Action __a, any * __other = nullptr, 267 type_info const * __info = nullptr) 268 { 269 return __h(__a, this, __other, __info); 270 } 271 272 template <class> 273 friend struct __any_imp::_SmallHandler; 274 template <class> 275 friend struct __any_imp::_LargeHandler; 276 277 template <class _ValueType> 278 friend typename add_pointer<typename add_const<_ValueType>::type>::type 279 any_cast(any const *) _NOEXCEPT; 280 281 template <class _ValueType> 282 friend typename add_pointer<_ValueType>::type 283 any_cast(any *) _NOEXCEPT; 284 285 _HandleFuncPtr __h; 286 _Storage __s; 287 }; 288 289 namespace __any_imp 290 { 291 292 template <class _Tp> 293 struct _LIBCPP_TYPE_VIS_ONLY _SmallHandler 294 { 295 _LIBCPP_INLINE_VISIBILITY 296 static void* __handle(_Action __act, any const * __this, any * __other, 297 type_info const * __info) 298 { 299 switch (__act) 300 { 301 case _Action::_Destroy: 302 __destroy(const_cast<any &>(*__this)); 303 return nullptr; 304 case _Action::_Copy: 305 __copy(*__this, *__other); 306 return nullptr; 307 case _Action::_Move: 308 __move(const_cast<any &>(*__this), *__other); 309 return nullptr; 310 case _Action::_Get: 311 return __get(const_cast<any &>(*__this), __info); 312 case _Action::_TypeInfo: 313 return __type_info(); 314 } 315 } 316 317 template <class _Up> 318 _LIBCPP_INLINE_VISIBILITY 319 static void __create(any & __dest, _Up && __v) 320 { 321 ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Up>(__v)); 322 __dest.__h = &_SmallHandler::__handle; 323 } 324 325 private: 326 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 327 static void __destroy(any & __this) 328 { 329 _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf)); 330 __value.~_Tp(); 331 __this.__h = nullptr; 332 } 333 334 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 335 static void __copy(any const & __this, any & __dest) 336 { 337 _SmallHandler::__create(__dest, *static_cast<_Tp const *>( 338 static_cast<void const *>(&__this.__s.__buf))); 339 } 340 341 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 342 static void __move(any & __this, any & __dest) 343 { 344 _SmallHandler::__create(__dest, _VSTD::move( 345 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf)))); 346 __destroy(__this); 347 } 348 349 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 350 static void* __get(any & __this, type_info const * __info) 351 { 352 #if !defined(_LIBCPP_NO_RTTI) 353 if (typeid(_Tp) == *__info) { 354 return static_cast<void*>(&__this.__s.__buf); 355 } 356 return nullptr; 357 #else 358 return static_cast<void*>(&__this.__s.__buf); 359 #endif 360 } 361 362 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 363 static void* __type_info() 364 { 365 #if !defined(_LIBCPP_NO_RTTI) 366 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 367 #else 368 return nullptr; 369 #endif 370 } 371 }; 372 373 template <class _Tp> 374 struct _LIBCPP_TYPE_VIS_ONLY _LargeHandler 375 { 376 _LIBCPP_INLINE_VISIBILITY 377 static void* __handle(_Action __act, any const * __this, any * __other, 378 type_info const * __info) 379 { 380 switch (__act) 381 { 382 case _Action::_Destroy: 383 __destroy(const_cast<any &>(*__this)); 384 return nullptr; 385 case _Action::_Copy: 386 __copy(*__this, *__other); 387 return nullptr; 388 case _Action::_Move: 389 __move(const_cast<any &>(*__this), *__other); 390 return nullptr; 391 case _Action::_Get: 392 return __get(const_cast<any &>(*__this), __info); 393 case _Action::_TypeInfo: 394 return __type_info(); 395 } 396 } 397 398 template <class _Up> 399 _LIBCPP_INLINE_VISIBILITY 400 static void __create(any & __dest, _Up && __v) 401 { 402 typedef allocator<_Tp> _Alloc; 403 typedef __allocator_destructor<_Alloc> _Dp; 404 _Alloc __a; 405 unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); 406 ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Up>(__v)); 407 __dest.__s.__ptr = __hold.release(); 408 __dest.__h = &_LargeHandler::__handle; 409 } 410 411 private: 412 413 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 414 static void __destroy(any & __this) 415 { 416 delete static_cast<_Tp*>(__this.__s.__ptr); 417 __this.__h = nullptr; 418 } 419 420 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 421 static void __copy(any const & __this, any & __dest) 422 { 423 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr)); 424 } 425 426 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 427 static void __move(any & __this, any & __dest) 428 { 429 __dest.__s.__ptr = __this.__s.__ptr; 430 __dest.__h = &_LargeHandler::__handle; 431 __this.__h = nullptr; 432 } 433 434 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 435 static void* __get(any & __this, type_info const * __info) 436 { 437 #if !defined(_LIBCPP_NO_RTTI) 438 if (typeid(_Tp) == *__info) { 439 return static_cast<void*>(__this.__s.__ptr); 440 } 441 return nullptr; 442 #else 443 return static_cast<void*>(__this.__s.__ptr); 444 #endif 445 } 446 447 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY 448 static void* __type_info() 449 { 450 #if !defined(_LIBCPP_NO_RTTI) 451 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 452 #else 453 return nullptr; 454 #endif 455 } 456 }; 457 458 } // namespace __any_imp 459 460 461 template <class _ValueType, class> 462 _LIBCPP_INLINE_VISIBILITY 463 any::any(_ValueType && __v) : __h(nullptr) 464 { 465 typedef typename decay<_ValueType>::type _Tp; 466 static_assert(is_copy_constructible<_Tp>::value, 467 "_ValueType must be CopyConstructible."); 468 typedef __any_imp::_Handler<_Tp> _HandlerType; 469 _HandlerType::__create(*this, _VSTD::forward<_ValueType>(__v)); 470 } 471 472 template <class _ValueType, class> 473 _LIBCPP_INLINE_VISIBILITY 474 any & 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 483 inline _LIBCPP_INLINE_VISIBILITY 484 void 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 502 inline _LIBCPP_INLINE_VISIBILITY 503 void swap(any & __lhs, any & __rhs) _NOEXCEPT 504 { 505 __lhs.swap(__rhs); 506 } 507 508 template <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 524 template <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 539 template <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 554 template <class _ValueType> 555 inline _LIBCPP_INLINE_VISIBILITY 556 typename add_pointer<typename add_const<_ValueType>::type>::type 557 any_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 564 template <class _ValueType> 565 _LIBCPP_INLINE_VISIBILITY 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