blob: 6f742cbdf73b2273b69c5b5a88d501d262da98d8 [file] [log] [blame]
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +00001// -*- 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_ANY
12#define _LIBCPP_ANY
13
14/*
15 any synopsis
16
17namespace std {
18
19 class bad_any_cast : public bad_cast
20 {
21 public:
22 virtual const char* what() const noexcept;
23 };
24
25 class any
26 {
27 public:
28
29 // 6.3.1 any construct/destruct
30 any() noexcept;
31
32 any(const any& other);
33 any(any&& other) noexcept;
34
35 template <class ValueType>
36 any(ValueType&& value);
37
38 ~any();
39
40 // 6.3.2 any assignments
41 any& operator=(const any& rhs);
42 any& operator=(any&& rhs) noexcept;
43
44 template <class ValueType>
45 any& operator=(ValueType&& rhs);
46
47 // 6.3.3 any modifiers
48 void reset() noexcept;
49 void swap(any& rhs) noexcept;
50
51 // 6.3.4 any observers
52 bool has_value() const noexcept;
53 const type_info& type() const noexcept;
54 };
55
56 // 6.4 Non-member functions
57 void swap(any& x, any& y) noexcept;
58
59 template <class T, class ...Args>
60 any make_any(Args&& ...args);
61 template <class T, class U, class ...Args>
62 any make_any(initializer_list<U>, Args&& ...args);
63
64 template<class ValueType>
65 ValueType any_cast(const any& operand);
66 template<class ValueType>
67 ValueType any_cast(any& operand);
68 template<class ValueType>
69 ValueType any_cast(any&& operand);
70
71 template<class ValueType>
72 const ValueType* any_cast(const any* operand) noexcept;
73 template<class ValueType>
74 ValueType* any_cast(any* operand) noexcept;
75
76} // namespace fundamentals_v1
77} // namespace experimental
78} // namespace std
79
80*/
81
82#include <experimental/__config>
83#include <memory>
84#include <new>
85#include <typeinfo>
86#include <type_traits>
87#include <cstdlib>
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +000088
89#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
90#pragma GCC system_header
91#endif
92
93namespace std {
94class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast
95{
96public:
97 virtual const char* what() const _NOEXCEPT;
98};
99} // namespace std
100
101_LIBCPP_BEGIN_NAMESPACE_STD
102
103#if _LIBCPP_STD_VER > 14
104
Marshall Clowed3e2292016-08-25 17:47:09 +0000105_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
106void __throw_bad_any_cast()
107{
108#ifndef _LIBCPP_NO_EXCEPTIONS
109 throw bad_any_cast();
110#else
111 _VSTD::abort();
112#endif
113}
114
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +0000115// Forward declarations
116class _LIBCPP_TYPE_VIS_ONLY any;
117
118template <class _ValueType>
119_LIBCPP_INLINE_VISIBILITY
120add_pointer_t<add_const_t<_ValueType>>
121any_cast(any const *) _NOEXCEPT;
122
123template <class _ValueType>
124_LIBCPP_INLINE_VISIBILITY
125add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT;
126
127namespace __any_imp
128{
129 using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>;
130
131 template <class _Tp>
132 using _IsSmallObject = integral_constant<bool
133 , sizeof(_Tp) <= sizeof(_Buffer)
134 && alignment_of<_Buffer>::value
135 % alignment_of<_Tp>::value == 0
136 && is_nothrow_move_constructible<_Tp>::value
137 >;
138
139 enum class _Action {
140 _Destroy,
141 _Copy,
142 _Move,
143 _Get,
144 _TypeInfo
145 };
146
147 template <class _Tp> struct _SmallHandler;
148 template <class _Tp> struct _LargeHandler;
149
150 template <class _Tp>
151 struct _LIBCPP_TYPE_VIS_ONLY __unique_typeinfo { static constexpr int __id = 0; };
152 template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id;
153
154 template <class _Tp>
155 inline _LIBCPP_INLINE_VISIBILITY
156 constexpr const void* __get_fallback_typeid() {
157 return &__unique_typeinfo<decay_t<_Tp>>::__id;
158 }
159
160 template <class _Tp>
161 inline _LIBCPP_INLINE_VISIBILITY
162 bool __compare_typeid(type_info const* __id, const void* __fallback_id)
163 {
164#if !defined(_LIBCPP_NO_RTTI)
165 if (__id && *__id == typeid(_Tp))
166 return true;
167#endif
168 if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>())
169 return true;
170 return false;
171 }
172
173 template <class _Tp>
174 using _Handler = conditional_t<
175 _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;
176
177} // namespace __any_imp
178
179class _LIBCPP_TYPE_VIS_ONLY any
180{
181public:
182 // construct/destruct
183 _LIBCPP_INLINE_VISIBILITY
184 constexpr any() _NOEXCEPT : __h(nullptr) {}
185
186 _LIBCPP_INLINE_VISIBILITY
187 any(any const & __other) : __h(nullptr)
188 {
189 if (__other.__h) __other.__call(_Action::_Copy, this);
190 }
191
192 _LIBCPP_INLINE_VISIBILITY
193 any(any && __other) _NOEXCEPT : __h(nullptr)
194 {
195 if (__other.__h) __other.__call(_Action::_Move, this);
196 }
197
198 template <
199 class _ValueType
200 , class = enable_if_t<
201 !is_same<decay_t<_ValueType>, any>::value &&
202 !__is_inplace_type<_ValueType>::value &&
203 is_copy_constructible<_ValueType>::value>
204 >
205 _LIBCPP_INLINE_VISIBILITY
206 any(_ValueType && __value);
207
208 template <class _Tp, class ..._Args,
209 class = enable_if_t<
210 is_constructible<_Tp, _Args...>::value &&
211 is_copy_constructible<_Tp>::value
212 >
213 >
214 _LIBCPP_INLINE_VISIBILITY
215 explicit any(in_place_type_t<_Tp>, _Args&&... __args);
216
217 template <class _Tp, class _Up, class ..._Args,
218 class = enable_if_t<
219 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
220 is_copy_constructible<_Tp>::value>
221 >
222 _LIBCPP_INLINE_VISIBILITY
223 explicit any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&... __args);
224
225 _LIBCPP_INLINE_VISIBILITY
226 ~any() { this->reset(); }
227
228 // assignments
229 _LIBCPP_INLINE_VISIBILITY
230 any & operator=(any const & __rhs) {
231 any(__rhs).swap(*this);
232 return *this;
233 }
234
235 _LIBCPP_INLINE_VISIBILITY
236 any & operator=(any && __rhs) _NOEXCEPT {
237 any(_VSTD::move(__rhs)).swap(*this);
238 return *this;
239 }
240
241 // TODO: Should this be constrained to disallow in_place types like the
242 // ValueType constructor?
243 template <
244 class _ValueType
245 , class = enable_if_t<
246 !is_same<decay_t<_ValueType>, any>::value
247 && is_copy_constructible<_ValueType>::value
248 && !__is_inplace_type<_ValueType>::value>
249 >
250 _LIBCPP_INLINE_VISIBILITY
251 any & operator=(_ValueType && __rhs);
252
253 template <class _Tp, class ..._Args,
254 class = enable_if_t<
255 is_constructible<_Tp, _Args...>::value &&
256 is_copy_constructible<_Tp>::value>
257 >
258 _LIBCPP_INLINE_VISIBILITY
259 void emplace(_Args&&... args);
260
261 template <class _Tp, class _Up, class ..._Args,
262 class = enable_if_t<
263 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
264 is_copy_constructible<_Tp>::value>
265 >
266 _LIBCPP_INLINE_VISIBILITY
267 void emplace(initializer_list<_Up>, _Args&&...);
268
269 // 6.3.3 any modifiers
270 _LIBCPP_INLINE_VISIBILITY
271 void reset() _NOEXCEPT { if (__h) this->__call(_Action::_Destroy); }
272
273 _LIBCPP_INLINE_VISIBILITY
274 void swap(any & __rhs) _NOEXCEPT;
275
276 // 6.3.4 any observers
277 _LIBCPP_INLINE_VISIBILITY
278 bool has_value() const _NOEXCEPT { return __h != nullptr; }
279
280#if !defined(_LIBCPP_NO_RTTI)
281 _LIBCPP_INLINE_VISIBILITY
282 const type_info & type() const _NOEXCEPT {
283 if (__h) {
284 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
285 } else {
286 return typeid(void);
287 }
288 }
289#endif
290
291private:
292 typedef __any_imp::_Action _Action;
293 using _HandleFuncPtr = void* (*)(_Action, any const *, any *, const type_info *,
294 const void* __fallback_info);
295
296 union _Storage {
297 constexpr _Storage() : __ptr(nullptr) {}
298 void * __ptr;
299 __any_imp::_Buffer __buf;
300 };
301
302 _LIBCPP_ALWAYS_INLINE
303 void * __call(_Action __a, any * __other = nullptr,
304 type_info const * __info = nullptr,
305 const void* __fallback_info = nullptr) const
306 {
307 return __h(__a, this, __other, __info, __fallback_info);
308 }
309
310 _LIBCPP_ALWAYS_INLINE
311 void * __call(_Action __a, any * __other = nullptr,
312 type_info const * __info = nullptr,
313 const void* __fallback_info = nullptr)
314 {
315 return __h(__a, this, __other, __info, __fallback_info);
316 }
317
318 template <class>
319 friend struct __any_imp::_SmallHandler;
320 template <class>
321 friend struct __any_imp::_LargeHandler;
322
323 template <class _ValueType>
324 friend add_pointer_t<add_const_t<_ValueType>>
325 any_cast(any const *) _NOEXCEPT;
326
327 template <class _ValueType>
328 friend add_pointer_t<_ValueType>
329 any_cast(any *) _NOEXCEPT;
330
331 _HandleFuncPtr __h = nullptr;
332 _Storage __s;
333};
334
335namespace __any_imp
336{
337 template <class _Tp>
338 struct _LIBCPP_TYPE_VIS_ONLY _SmallHandler
339 {
340 _LIBCPP_INLINE_VISIBILITY
341 static void* __handle(_Action __act, any const * __this, any * __other,
342 type_info const * __info, const void* __fallback_info)
343 {
344 switch (__act)
345 {
346 case _Action::_Destroy:
347 __destroy(const_cast<any &>(*__this));
348 return nullptr;
349 case _Action::_Copy:
350 __copy(*__this, *__other);
351 return nullptr;
352 case _Action::_Move:
353 __move(const_cast<any &>(*__this), *__other);
354 return nullptr;
355 case _Action::_Get:
356 return __get(const_cast<any &>(*__this), __info, __fallback_info);
357 case _Action::_TypeInfo:
358 return __type_info();
359 }
360 }
361
362 template <class ..._Args>
363 _LIBCPP_INLINE_VISIBILITY
364 static void __create(any & __dest, _Args&&... __args) {
365 ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
366 __dest.__h = &_SmallHandler::__handle;
367 }
368
369 private:
370 _LIBCPP_INLINE_VISIBILITY
371 static void __destroy(any & __this) {
372 _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
373 __value.~_Tp();
374 __this.__h = nullptr;
375 }
376
377 _LIBCPP_INLINE_VISIBILITY
378 static void __copy(any const & __this, any & __dest) {
379 _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
380 static_cast<void const *>(&__this.__s.__buf)));
381 }
382
383 _LIBCPP_INLINE_VISIBILITY
384 static void __move(any & __this, any & __dest) {
385 _SmallHandler::__create(__dest, _VSTD::move(
386 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
387 __destroy(__this);
388 }
389
390 _LIBCPP_INLINE_VISIBILITY
391 static void* __get(any & __this,
392 type_info const * __info,
393 const void* __fallback_id)
394 {
395 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
396 return static_cast<void*>(&__this.__s.__buf);
397 return nullptr;
398 }
399
400 _LIBCPP_INLINE_VISIBILITY
401 static void* __type_info()
402 {
403#if !defined(_LIBCPP_NO_RTTI)
404 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
405#else
406 return nullptr;
407#endif
408 }
409 };
410
411 template <class _Tp>
412 struct _LIBCPP_TYPE_VIS_ONLY _LargeHandler
413 {
414 _LIBCPP_INLINE_VISIBILITY
415 static void* __handle(_Action __act, any const * __this,
416 any * __other, type_info const * __info,
417 void const* __fallback_info)
418 {
419 switch (__act)
420 {
421 case _Action::_Destroy:
422 __destroy(const_cast<any &>(*__this));
423 return nullptr;
424 case _Action::_Copy:
425 __copy(*__this, *__other);
426 return nullptr;
427 case _Action::_Move:
428 __move(const_cast<any &>(*__this), *__other);
429 return nullptr;
430 case _Action::_Get:
431 return __get(const_cast<any &>(*__this), __info, __fallback_info);
432 case _Action::_TypeInfo:
433 return __type_info();
434 }
435 }
436
437 template <class ..._Args>
438 _LIBCPP_INLINE_VISIBILITY
439 static void __create(any & __dest, _Args&&... __args) {
440 typedef allocator<_Tp> _Alloc;
441 typedef __allocator_destructor<_Alloc> _Dp;
442 _Alloc __a;
443 unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
444 ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
445 __dest.__s.__ptr = __hold.release();
446 __dest.__h = &_LargeHandler::__handle;
447 }
448
449 private:
450
451 _LIBCPP_INLINE_VISIBILITY
452 static void __destroy(any & __this){
453 delete static_cast<_Tp*>(__this.__s.__ptr);
454 __this.__h = nullptr;
455 }
456
457 _LIBCPP_INLINE_VISIBILITY
458 static void __copy(any const & __this, any & __dest) {
459 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
460 }
461
462 _LIBCPP_INLINE_VISIBILITY
463 static void __move(any & __this, any & __dest) {
464 __dest.__s.__ptr = __this.__s.__ptr;
465 __dest.__h = &_LargeHandler::__handle;
466 __this.__h = nullptr;
467 }
468
469 _LIBCPP_INLINE_VISIBILITY
470 static void* __get(any & __this, type_info const * __info,
471 void const* __fallback_info)
472 {
473 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
474 return static_cast<void*>(__this.__s.__ptr);
475 return nullptr;
476
477 }
478
479 _LIBCPP_INLINE_VISIBILITY
480 static void* __type_info()
481 {
482#if !defined(_LIBCPP_NO_RTTI)
483 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
484#else
485 return nullptr;
486#endif
487 }
488 };
489
490} // namespace __any_imp
491
492
493template <class _ValueType, class>
494any::any(_ValueType && __v) : __h(nullptr)
495{
496 typedef typename decay<_ValueType>::type _Tp;
497 static_assert(is_copy_constructible<_Tp>::value,
498 "_ValueType must be CopyConstructible.");
499 using _ForwardTp = conditional_t<
500 is_move_constructible<_Tp>::value, _ValueType, _ValueType&>;
501 typedef __any_imp::_Handler<_Tp> _HandlerType;
502 _HandlerType::__create(*this, _VSTD::forward<_ForwardTp>(__v));
503}
504
505template <class _Tp, class ..._Args, class>
506any::any(in_place_type_t<_Tp>, _Args&&... __args) {
507 using _Hp = __any_imp::_Handler<_Tp>;
508 _Hp::__create(*this, _VSTD::forward<_Args>(__args)...);
509};
510
511template <class _Tp, class _Up, class ..._Args, class>
512any::any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) {
513 using _Hp = __any_imp::_Handler<_Tp>;
514 _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
515}
516
517template <class _ValueType, class>
518inline _LIBCPP_INLINE_VISIBILITY
519any & any::operator=(_ValueType && __v)
520{
521 typedef typename decay<_ValueType>::type _Tp;
522 static_assert(is_copy_constructible<_Tp>::value,
523 "_ValueType must be CopyConstructible.");
524 any(_VSTD::forward<_ValueType>(__v)).swap(*this);
525 return *this;
526}
527
528template <class _Tp, class ..._Args, class>
529inline _LIBCPP_INLINE_VISIBILITY
530void any::emplace(_Args&&... __args) {
531 using _Hp = __any_imp::_Handler<_Tp>;
532 reset();
533 _Hp::__create(*this, _VSTD::forward<_Args>(__args)...);
534}
535
536template <class _Tp, class _Up, class ..._Args, class>
537inline _LIBCPP_INLINE_VISIBILITY
538void any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
539 using _Hp = __any_imp::_Handler<_Tp>;
540 reset();
541 _Hp::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
542}
543
544inline _LIBCPP_INLINE_VISIBILITY
545void any::swap(any & __rhs) _NOEXCEPT
546{
547 if (__h && __rhs.__h) {
548 any __tmp;
549 __rhs.__call(_Action::_Move, &__tmp);
550 this->__call(_Action::_Move, &__rhs);
551 __tmp.__call(_Action::_Move, this);
552 }
553 else if (__h) {
554 this->__call(_Action::_Move, &__rhs);
555 }
556 else if (__rhs.__h) {
557 __rhs.__call(_Action::_Move, this);
558 }
559}
560
561// 6.4 Non-member functions
562
563inline _LIBCPP_INLINE_VISIBILITY
564void swap(any & __lhs, any & __rhs) _NOEXCEPT
565{
566 __lhs.swap(__rhs);
567}
568
569template <class _Tp, class ..._Args>
570inline _LIBCPP_INLINE_VISIBILITY
571any make_any(_Args&&... __args) {
572 return any(in_place<_Tp>, _VSTD::forward<_Args>(__args)...);
573}
574
575template <class _Tp, class _Up, class ..._Args>
576inline _LIBCPP_INLINE_VISIBILITY
577any make_any(initializer_list<_Up> __il, _Args&&... __args) {
578 return any(in_place<_Tp>, __il, _VSTD::forward<_Args>(__args)...);
579}
580
581template <class _ValueType>
582inline _LIBCPP_INLINE_VISIBILITY
583_ValueType any_cast(any const & __v)
584{
585 static_assert(
586 is_reference<_ValueType>::value
587 || is_copy_constructible<_ValueType>::value,
588 "_ValueType is required to be a reference or a CopyConstructible type.");
589 using _Tp = add_const_t<remove_reference_t<_ValueType>>;
590 _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
591 if (__tmp == nullptr)
Marshall Clowed3e2292016-08-25 17:47:09 +0000592 __throw_bad_any_cast();
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +0000593 return *__tmp;
594}
595
596template <class _ValueType>
597inline _LIBCPP_INLINE_VISIBILITY
598_ValueType any_cast(any & __v)
599{
600 static_assert(
601 is_reference<_ValueType>::value
602 || is_copy_constructible<_ValueType>::value,
603 "_ValueType is required to be a reference or a CopyConstructible type.");
604 typedef typename remove_reference<_ValueType>::type _Tp;
605 _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
606 if (__tmp == nullptr)
Marshall Clowed3e2292016-08-25 17:47:09 +0000607 __throw_bad_any_cast();
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +0000608 return *__tmp;
609}
610
611template <class _ValueType>
612inline _LIBCPP_INLINE_VISIBILITY
613_ValueType any_cast(any && __v)
614{
615 static_assert(
616 is_reference<_ValueType>::value
617 || is_copy_constructible<_ValueType>::value,
618 "_ValueType is required to be a reference or a CopyConstructible type.");
619 typedef typename remove_reference<_ValueType>::type _Tp;
620 using _ForwardTp = conditional_t<
621 is_reference<_ValueType>::value,
622 _ValueType,
623 conditional_t<is_move_constructible<_Tp>::value, _Tp, _Tp&>
624 >;
625 _Tp * __tmp = _VSTD::any_cast<_Tp>(&__v);
626 if (__tmp == nullptr)
Marshall Clowed3e2292016-08-25 17:47:09 +0000627 __throw_bad_any_cast();
Eric Fiselierf6b3bfe2016-08-11 03:13:11 +0000628 return _VSTD::forward<_ForwardTp>(*__tmp);
629}
630
631template <class _ValueType>
632inline _LIBCPP_INLINE_VISIBILITY
633add_pointer_t<add_const_t<_ValueType>>
634any_cast(any const * __any) _NOEXCEPT
635{
636 static_assert(!is_reference<_ValueType>::value,
637 "_ValueType may not be a reference.");
638 return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any));
639}
640
641template <class _ValueType>
642add_pointer_t<_ValueType>
643any_cast(any * __any) _NOEXCEPT
644{
645 using __any_imp::_Action;
646 static_assert(!is_reference<_ValueType>::value,
647 "_ValueType may not be a reference.");
648 typedef typename add_pointer<_ValueType>::type _ReturnType;
649 if (__any && __any->__h) {
650 return static_cast<_ReturnType>(
651 __any->__call(_Action::_Get, nullptr,
652#if !defined(_LIBCPP_NO_RTTI)
653 &typeid(_ValueType),
654#else
655 nullptr,
656#endif
657 __any_imp::__get_fallback_typeid<_ValueType>()
658 ));
659 }
660 return nullptr;
661}
662
663#endif // _LIBCPP_STD_VER > 14
664
665_LIBCPP_END_NAMESPACE_STD
666
667#endif // _LIBCPP_ANY