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 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 void __throw_bad_any_cast()
103 #ifndef _LIBCPP_NO_EXCEPTIONS
104 throw bad_any_cast();
110 // Forward declarations
113 template <class _ValueType>
114 typename add_pointer<typename add_const<_ValueType>::type>::type
115 _LIBCPP_INLINE_VISIBILITY
116 any_cast(any const *) _NOEXCEPT;
118 template <class _ValueType>
119 typename add_pointer<_ValueType>::type
120 _LIBCPP_INLINE_VISIBILITY
121 any_cast(any *) _NOEXCEPT;
125 typedef typename aligned_storage<3*sizeof(void*), alignment_of<void*>::value>::type
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
148 struct _SmallHandler;
151 struct _LargeHandler;
154 using _Handler = typename conditional<_IsSmallObject<_Tp>::value
158 template <class _ValueType>
159 using _EnableIfNotAny = typename
161 !is_same<typename decay<_ValueType>::type, any>::value
164 } // namespace __any_imp
169 // 6.3.1 any construct/destruct
170 _LIBCPP_INLINE_VISIBILITY
171 any() _NOEXCEPT : __h(nullptr) {}
173 _LIBCPP_INLINE_VISIBILITY
174 any(any const & __other) : __h(nullptr)
176 if (__other.__h) __other.__call(_Action::_Copy, this);
179 _LIBCPP_INLINE_VISIBILITY
180 any(any && __other) _NOEXCEPT : __h(nullptr)
182 if (__other.__h) __other.__call(_Action::_Move, this);
187 , class = __any_imp::_EnableIfNotAny<_ValueType>
189 _LIBCPP_INLINE_VISIBILITY
190 any(_ValueType && __value);
192 _LIBCPP_INLINE_VISIBILITY
198 // 6.3.2 any assignments
199 _LIBCPP_INLINE_VISIBILITY
200 any & operator=(any const & __rhs)
202 any(__rhs).swap(*this);
206 _LIBCPP_INLINE_VISIBILITY
207 any & operator=(any && __rhs) _NOEXCEPT
209 any(_VSTD::move(__rhs)).swap(*this);
215 , class = __any_imp::_EnableIfNotAny<_ValueType>
217 _LIBCPP_INLINE_VISIBILITY
218 any & operator=(_ValueType && __rhs);
220 // 6.3.3 any modifiers
221 _LIBCPP_INLINE_VISIBILITY
222 void clear() _NOEXCEPT
224 if (__h) this->__call(_Action::_Destroy);
227 _LIBCPP_INLINE_VISIBILITY
228 void swap(any & __rhs) _NOEXCEPT;
230 // 6.3.4 any observers
231 _LIBCPP_INLINE_VISIBILITY
232 bool empty() const _NOEXCEPT
234 return __h == nullptr;
237 #if !defined(_LIBCPP_NO_RTTI)
238 _LIBCPP_INLINE_VISIBILITY
239 const type_info & type() const _NOEXCEPT
242 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
250 typedef __any_imp::_Action _Action;
252 typedef void* (*_HandleFuncPtr)(_Action, any const *, any *, const type_info *);
257 __any_imp::_Buffer __buf;
260 _LIBCPP_ALWAYS_INLINE
261 void * __call(_Action __a, any * __other = nullptr,
262 type_info const * __info = nullptr) const
264 return __h(__a, this, __other, __info);
267 _LIBCPP_ALWAYS_INLINE
268 void * __call(_Action __a, any * __other = nullptr,
269 type_info const * __info = nullptr)
271 return __h(__a, this, __other, __info);
275 friend struct __any_imp::_SmallHandler;
277 friend struct __any_imp::_LargeHandler;
279 template <class _ValueType>
280 friend typename add_pointer<typename add_const<_ValueType>::type>::type
281 any_cast(any const *) _NOEXCEPT;
283 template <class _ValueType>
284 friend typename add_pointer<_ValueType>::type
285 any_cast(any *) _NOEXCEPT;
295 struct _LIBCPP_TEMPLATE_VIS _SmallHandler
297 _LIBCPP_INLINE_VISIBILITY
298 static void* __handle(_Action __act, any const * __this, any * __other,
299 type_info const * __info)
303 case _Action::_Destroy:
304 __destroy(const_cast<any &>(*__this));
307 __copy(*__this, *__other);
310 __move(const_cast<any &>(*__this), *__other);
313 return __get(const_cast<any &>(*__this), __info);
314 case _Action::_TypeInfo:
315 return __type_info();
320 _LIBCPP_INLINE_VISIBILITY
321 static void __create(any & __dest, _Up && __v)
323 ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Up>(__v));
324 __dest.__h = &_SmallHandler::__handle;
328 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
329 static void __destroy(any & __this)
331 _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
333 __this.__h = nullptr;
336 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
337 static void __copy(any const & __this, any & __dest)
339 _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
340 static_cast<void const *>(&__this.__s.__buf)));
343 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
344 static void __move(any & __this, any & __dest)
346 _SmallHandler::__create(__dest, _VSTD::move(
347 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
351 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
352 static void* __get(any & __this, type_info const * __info)
354 #if !defined(_LIBCPP_NO_RTTI)
355 if (typeid(_Tp) == *__info) {
356 return static_cast<void*>(&__this.__s.__buf);
360 return static_cast<void*>(&__this.__s.__buf);
364 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
365 static void* __type_info()
367 #if !defined(_LIBCPP_NO_RTTI)
368 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
376 struct _LIBCPP_TEMPLATE_VIS _LargeHandler
378 _LIBCPP_INLINE_VISIBILITY
379 static void* __handle(_Action __act, any const * __this, any * __other,
380 type_info const * __info)
384 case _Action::_Destroy:
385 __destroy(const_cast<any &>(*__this));
388 __copy(*__this, *__other);
391 __move(const_cast<any &>(*__this), *__other);
394 return __get(const_cast<any &>(*__this), __info);
395 case _Action::_TypeInfo:
396 return __type_info();
401 _LIBCPP_INLINE_VISIBILITY
402 static void __create(any & __dest, _Up && __v)
404 typedef allocator<_Tp> _Alloc;
405 typedef __allocator_destructor<_Alloc> _Dp;
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;
415 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
416 static void __destroy(any & __this)
418 delete static_cast<_Tp*>(__this.__s.__ptr);
419 __this.__h = nullptr;
422 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
423 static void __copy(any const & __this, any & __dest)
425 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
428 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
429 static void __move(any & __this, any & __dest)
431 __dest.__s.__ptr = __this.__s.__ptr;
432 __dest.__h = &_LargeHandler::__handle;
433 __this.__h = nullptr;
436 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
437 static void* __get(any & __this, type_info const * __info)
439 #if !defined(_LIBCPP_NO_RTTI)
440 if (typeid(_Tp) == *__info) {
441 return static_cast<void*>(__this.__s.__ptr);
445 return static_cast<void*>(__this.__s.__ptr);
449 _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
450 static void* __type_info()
452 #if !defined(_LIBCPP_NO_RTTI)
453 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
460 } // namespace __any_imp
463 template <class _ValueType, class>
464 any::any(_ValueType && __v) : __h(nullptr)
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));
473 template <class _ValueType, class>
474 any & any::operator=(_ValueType && __v)
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);
484 void any::swap(any & __rhs) _NOEXCEPT
486 if (__h && __rhs.__h) {
488 __rhs.__call(_Action::_Move, &__tmp);
489 this->__call(_Action::_Move, &__rhs);
490 __tmp.__call(_Action::_Move, this);
493 this->__call(_Action::_Move, &__rhs);
495 else if (__rhs.__h) {
496 __rhs.__call(_Action::_Move, this);
500 // 6.4 Non-member functions
502 inline _LIBCPP_INLINE_VISIBILITY
503 void swap(any & __lhs, any & __rhs) _NOEXCEPT
508 template <class _ValueType>
509 _LIBCPP_INLINE_VISIBILITY
510 _ValueType any_cast(any const & __v)
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
518 _Tp * __tmp = any_cast<_Tp>(&__v);
519 if (__tmp == nullptr)
520 __throw_bad_any_cast();
524 template <class _ValueType>
525 _LIBCPP_INLINE_VISIBILITY
526 _ValueType any_cast(any & __v)
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();
539 template <class _ValueType>
540 _LIBCPP_INLINE_VISIBILITY
541 _ValueType any_cast(any && __v)
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();
554 template <class _ValueType>
556 typename add_pointer<typename add_const<_ValueType>::type>::type
557 any_cast(any const * __any) _NOEXCEPT
559 static_assert(!is_reference<_ValueType>::value,
560 "_ValueType may not be a reference.");
561 return any_cast<_ValueType>(const_cast<any *>(__any));
564 template <class _ValueType>
565 typename add_pointer<_ValueType>::type
566 any_cast(any * __any) _NOEXCEPT
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) {
574 return static_cast<_ReturnType>(
575 __any->__call(_Action::_Get, nullptr,
576 #if !defined(_LIBCPP_NO_RTTI)
587 #endif // _LIBCPP_STD_VER > 11
589 _LIBCPP_END_NAMESPACE_LFTS
591 #endif // _LIBCPP_EXPERIMENTAL_ANY