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