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