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