2 //===------------------------------ any -----------------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_EXPERIMENTAL_ANY
12 #define _LIBCPP_EXPERIMENTAL_ANY
15 experimental/any synopsis
18 namespace experimental {
19 inline namespace fundamentals_v1 {
21 class bad_any_cast : public bad_cast
24 virtual const char* what() const noexcept;
31 // 6.3.1 any construct/destruct
34 any(const any& other);
35 any(any&& other) noexcept;
37 template <class ValueType>
38 any(ValueType&& value);
42 // 6.3.2 any assignments
43 any& operator=(const any& rhs);
44 any& operator=(any&& rhs) noexcept;
46 template <class ValueType>
47 any& operator=(ValueType&& rhs);
49 // 6.3.3 any modifiers
50 void clear() noexcept;
51 void swap(any& rhs) noexcept;
53 // 6.3.4 any observers
54 bool empty() const noexcept;
55 const type_info& type() const noexcept;
58 // 6.4 Non-member functions
59 void swap(any& x, any& y) noexcept;
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);
68 template<class ValueType>
69 const ValueType* any_cast(const any* operand) noexcept;
70 template<class ValueType>
71 ValueType* any_cast(any* operand) noexcept;
73 } // namespace fundamentals_v1
74 } // namespace experimental
79 #include <experimental/__config>
83 #include <type_traits>
86 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
87 #pragma GCC system_header
90 _LIBCPP_BEGIN_NAMESPACE_LFTS
92 class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
95 virtual const char* what() const _NOEXCEPT;
98 #if _LIBCPP_STD_VER > 11 // C++ > 11
100 _LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
101 _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
102 void __throw_bad_any_cast()
104 #ifndef _LIBCPP_NO_EXCEPTIONS
105 throw bad_any_cast();
111 // Forward declarations
114 template <class _ValueType>
115 typename add_pointer<typename add_const<_ValueType>::type>::type
116 _LIBCPP_INLINE_VISIBILITY
117 any_cast(any const *) _NOEXCEPT;
119 template <class _ValueType>
120 typename add_pointer<_ValueType>::type
121 _LIBCPP_INLINE_VISIBILITY
122 any_cast(any *) _NOEXCEPT;
126 typedef typename aligned_storage<3*sizeof(void*), alignment_of<void*>::value>::type
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
149 struct _SmallHandler;
152 struct _LargeHandler;
155 using _Handler = typename conditional<_IsSmallObject<_Tp>::value
159 template <class _ValueType>
160 using _EnableIfNotAny = typename
162 !is_same<typename decay<_ValueType>::type, any>::value
165 } // namespace __any_imp
170 // 6.3.1 any construct/destruct
171 _LIBCPP_INLINE_VISIBILITY
172 any() _NOEXCEPT : __h(nullptr) {}
174 _LIBCPP_INLINE_VISIBILITY
175 any(any const & __other) : __h(nullptr)
177 if (__other.__h) __other.__call(_Action::_Copy, this);
180 _LIBCPP_INLINE_VISIBILITY
181 any(any && __other) _NOEXCEPT : __h(nullptr)
183 if (__other.__h) __other.__call(_Action::_Move, this);
188 , class = __any_imp::_EnableIfNotAny<_ValueType>
190 _LIBCPP_INLINE_VISIBILITY
191 any(_ValueType && __value);
193 _LIBCPP_INLINE_VISIBILITY
199 // 6.3.2 any assignments
200 _LIBCPP_INLINE_VISIBILITY
201 any & operator=(any const & __rhs)
203 any(__rhs).swap(*this);
207 _LIBCPP_INLINE_VISIBILITY
208 any & operator=(any && __rhs) _NOEXCEPT
210 any(_VSTD::move(__rhs)).swap(*this);
216 , class = __any_imp::_EnableIfNotAny<_ValueType>
218 _LIBCPP_INLINE_VISIBILITY
219 any & operator=(_ValueType && __rhs);
221 // 6.3.3 any modifiers
222 _LIBCPP_INLINE_VISIBILITY
223 void clear() _NOEXCEPT
225 if (__h) this->__call(_Action::_Destroy);
228 _LIBCPP_INLINE_VISIBILITY
229 void swap(any & __rhs) _NOEXCEPT;
231 // 6.3.4 any observers
232 _LIBCPP_INLINE_VISIBILITY
233 bool empty() const _NOEXCEPT
235 return __h == nullptr;
238 #if !defined(_LIBCPP_NO_RTTI)
239 _LIBCPP_INLINE_VISIBILITY
240 const type_info & type() const _NOEXCEPT
243 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
251 typedef __any_imp::_Action _Action;
253 typedef void* (*_HandleFuncPtr)(_Action, any const *, any *, const type_info *);
258 __any_imp::_Buffer __buf;
261 _LIBCPP_ALWAYS_INLINE
262 void * __call(_Action __a, any * __other = nullptr,
263 type_info const * __info = nullptr) const
265 return __h(__a, this, __other, __info);
268 _LIBCPP_ALWAYS_INLINE
269 void * __call(_Action __a, any * __other = nullptr,
270 type_info const * __info = nullptr)
272 return __h(__a, this, __other, __info);
276 friend struct __any_imp::_SmallHandler;
278 friend struct __any_imp::_LargeHandler;
280 template <class _ValueType>
281 friend typename add_pointer<typename add_const<_ValueType>::type>::type
282 any_cast(any const *) _NOEXCEPT;
284 template <class _ValueType>
285 friend typename add_pointer<_ValueType>::type
286 any_cast(any *) _NOEXCEPT;
296 struct _LIBCPP_TEMPLATE_VIS _SmallHandler
298 _LIBCPP_INLINE_VISIBILITY
299 static void* __handle(_Action __act, any const * __this, any * __other,
300 type_info const * __info)
304 case _Action::_Destroy:
305 __destroy(const_cast<any &>(*__this));
308 __copy(*__this, *__other);
311 __move(const_cast<any &>(*__this), *__other);
314 return __get(const_cast<any &>(*__this), __info);
315 case _Action::_TypeInfo:
316 return __type_info();
321 _LIBCPP_INLINE_VISIBILITY
322 static void __create(any & __dest, _Up && __v)
324 ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Up>(__v));
325 __dest.__h = &_SmallHandler::__handle;
329 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
330 static void __destroy(any & __this)
332 _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
334 __this.__h = nullptr;
337 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
338 static void __copy(any const & __this, any & __dest)
340 _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
341 static_cast<void const *>(&__this.__s.__buf)));
344 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
345 static void __move(any & __this, any & __dest)
347 _SmallHandler::__create(__dest, _VSTD::move(
348 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
352 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
353 static void* __get(any & __this, type_info const * __info)
355 #if !defined(_LIBCPP_NO_RTTI)
356 if (typeid(_Tp) == *__info) {
357 return static_cast<void*>(&__this.__s.__buf);
361 return static_cast<void*>(&__this.__s.__buf);
365 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
366 static void* __type_info()
368 #if !defined(_LIBCPP_NO_RTTI)
369 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
377 struct _LIBCPP_TEMPLATE_VIS _LargeHandler
379 _LIBCPP_INLINE_VISIBILITY
380 static void* __handle(_Action __act, any const * __this, any * __other,
381 type_info const * __info)
385 case _Action::_Destroy:
386 __destroy(const_cast<any &>(*__this));
389 __copy(*__this, *__other);
392 __move(const_cast<any &>(*__this), *__other);
395 return __get(const_cast<any &>(*__this), __info);
396 case _Action::_TypeInfo:
397 return __type_info();
402 _LIBCPP_INLINE_VISIBILITY
403 static void __create(any & __dest, _Up && __v)
405 typedef allocator<_Tp> _Alloc;
406 typedef __allocator_destructor<_Alloc> _Dp;
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;
416 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
417 static void __destroy(any & __this)
419 delete static_cast<_Tp*>(__this.__s.__ptr);
420 __this.__h = nullptr;
423 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
424 static void __copy(any const & __this, any & __dest)
426 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
429 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
430 static void __move(any & __this, any & __dest)
432 __dest.__s.__ptr = __this.__s.__ptr;
433 __dest.__h = &_LargeHandler::__handle;
434 __this.__h = nullptr;
437 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
438 static void* __get(any & __this, type_info const * __info)
440 #if !defined(_LIBCPP_NO_RTTI)
441 if (typeid(_Tp) == *__info) {
442 return static_cast<void*>(__this.__s.__ptr);
446 return static_cast<void*>(__this.__s.__ptr);
450 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
451 static void* __type_info()
453 #if !defined(_LIBCPP_NO_RTTI)
454 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
461 } // namespace __any_imp
464 template <class _ValueType, class>
465 any::any(_ValueType && __v) : __h(nullptr)
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));
474 template <class _ValueType, class>
475 any & any::operator=(_ValueType && __v)
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);
485 void any::swap(any & __rhs) _NOEXCEPT
487 if (__h && __rhs.__h) {
489 __rhs.__call(_Action::_Move, &__tmp);
490 this->__call(_Action::_Move, &__rhs);
491 __tmp.__call(_Action::_Move, this);
494 this->__call(_Action::_Move, &__rhs);
496 else if (__rhs.__h) {
497 __rhs.__call(_Action::_Move, this);
501 // 6.4 Non-member functions
503 inline _LIBCPP_INLINE_VISIBILITY
504 void swap(any & __lhs, any & __rhs) _NOEXCEPT
509 template <class _ValueType>
510 _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
511 _ValueType any_cast(any const & __v)
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
519 _Tp * __tmp = any_cast<_Tp>(&__v);
520 if (__tmp == nullptr)
521 __throw_bad_any_cast();
525 template <class _ValueType>
526 _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
527 _ValueType any_cast(any & __v)
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();
540 template <class _ValueType>
541 _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
542 _ValueType any_cast(any && __v)
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();
555 template <class _ValueType>
557 typename add_pointer<typename add_const<_ValueType>::type>::type
558 any_cast(any const * __any) _NOEXCEPT
560 static_assert(!is_reference<_ValueType>::value,
561 "_ValueType may not be a reference.");
562 return any_cast<_ValueType>(const_cast<any *>(__any));
565 template <class _ValueType>
566 typename add_pointer<_ValueType>::type
567 any_cast(any * __any) _NOEXCEPT
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) {
575 return static_cast<_ReturnType>(
576 __any->__call(_Action::_Get, nullptr,
577 #if !defined(_LIBCPP_NO_RTTI)
588 #endif // _LIBCPP_STD_VER > 11
590 _LIBCPP_END_NAMESPACE_LFTS
592 #endif // _LIBCPP_EXPERIMENTAL_ANY