]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/include/experimental/any
Merge libc++ r291274, and update the library Makefile.
[FreeBSD/FreeBSD.git] / contrib / libc++ / include / experimental / any
1 // -*- 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_EXPERIMENTAL_ANY
12 #define _LIBCPP_EXPERIMENTAL_ANY
13
14 /*
15    experimental/any synopsis
16
17 namespace std {
18 namespace experimental {
19 inline namespace fundamentals_v1 {
20
21   class bad_any_cast : public bad_cast
22   {
23   public:
24     virtual const char* what() const noexcept;
25   };
26
27   class any
28   {
29   public:
30
31     // 6.3.1 any construct/destruct
32     any() noexcept;
33
34     any(const any& other);
35     any(any&& other) noexcept;
36
37     template <class ValueType>
38       any(ValueType&& value);
39
40     ~any();
41
42     // 6.3.2 any assignments
43     any& operator=(const any& rhs);
44     any& operator=(any&& rhs) noexcept;
45
46     template <class ValueType>
47       any& operator=(ValueType&& rhs);
48
49     // 6.3.3 any modifiers
50     void clear() noexcept;
51     void swap(any& rhs) noexcept;
52
53     // 6.3.4 any observers
54     bool empty() const noexcept;
55     const type_info& type() const noexcept;
56   };
57
58    // 6.4 Non-member functions
59   void swap(any& x, any& y) noexcept;
60
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);
67
68   template<class ValueType>
69     const ValueType* any_cast(const any* operand) noexcept;
70   template<class ValueType>
71     ValueType* any_cast(any* operand) noexcept;
72
73 } // namespace fundamentals_v1
74 } // namespace experimental
75 } // namespace std
76
77 */
78
79 #include <experimental/__config>
80 #include <memory>
81 #include <new>
82 #include <typeinfo>
83 #include <type_traits>
84 #include <cstdlib>
85
86 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
87 #pragma GCC system_header
88 #endif
89
90 _LIBCPP_BEGIN_NAMESPACE_LFTS
91
92 class _LIBCPP_EXCEPTION_ABI bad_any_cast : public bad_cast
93 {
94 public:
95     virtual const char* what() const _NOEXCEPT;
96 };
97
98 #if _LIBCPP_STD_VER > 11                                            // C++ > 11
99
100 _LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
101 void __throw_bad_any_cast()
102 {
103 #ifndef _LIBCPP_NO_EXCEPTIONS
104     throw bad_any_cast();
105 #else
106     _VSTD::abort();
107 #endif
108 }
109
110 // Forward declarations
111 class any;
112
113 template <class _ValueType>
114 typename add_pointer<typename add_const<_ValueType>::type>::type
115 _LIBCPP_INLINE_VISIBILITY
116 any_cast(any const *) _NOEXCEPT;
117
118 template <class _ValueType>
119 typename add_pointer<_ValueType>::type
120 _LIBCPP_INLINE_VISIBILITY
121 any_cast(any *) _NOEXCEPT;
122
123 namespace __any_imp
124 {
125   typedef typename aligned_storage<3*sizeof(void*), alignment_of<void*>::value>::type
126     _Buffer;
127
128   template <class _Tp>
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
135         >
136   {};
137
138   enum class _Action
139   {
140     _Destroy,
141     _Copy,
142     _Move,
143     _Get,
144     _TypeInfo
145   };
146
147   template <class _Tp>
148   struct _SmallHandler;
149
150   template <class _Tp>
151   struct _LargeHandler;
152
153   template <class _Tp>
154   using _Handler = typename conditional<_IsSmallObject<_Tp>::value
155                                       , _SmallHandler<_Tp>
156                                       , _LargeHandler<_Tp>
157                                     >::type;
158   template <class _ValueType>
159   using _EnableIfNotAny = typename
160     enable_if<
161       !is_same<typename decay<_ValueType>::type, any>::value
162     >::type;
163
164 } // namespace __any_imp
165
166 class any
167 {
168 public:
169   // 6.3.1 any construct/destruct
170   _LIBCPP_INLINE_VISIBILITY
171   any() _NOEXCEPT : __h(nullptr) {}
172
173   _LIBCPP_INLINE_VISIBILITY
174   any(any const & __other) : __h(nullptr)
175   {
176     if (__other.__h) __other.__call(_Action::_Copy, this);
177   }
178
179   _LIBCPP_INLINE_VISIBILITY
180   any(any && __other) _NOEXCEPT : __h(nullptr)
181   {
182     if (__other.__h) __other.__call(_Action::_Move, this);
183   }
184
185   template <
186       class _ValueType
187     , class = __any_imp::_EnableIfNotAny<_ValueType>
188     >
189   _LIBCPP_INLINE_VISIBILITY
190   any(_ValueType && __value);
191
192   _LIBCPP_INLINE_VISIBILITY
193   ~any()
194   {
195     this->clear();
196   }
197
198   // 6.3.2 any assignments
199   _LIBCPP_INLINE_VISIBILITY
200   any & operator=(any const & __rhs)
201   {
202     any(__rhs).swap(*this);
203     return *this;
204   }
205
206   _LIBCPP_INLINE_VISIBILITY
207   any & operator=(any && __rhs) _NOEXCEPT
208   {
209     any(_VSTD::move(__rhs)).swap(*this);
210     return *this;
211   }
212
213   template <
214       class _ValueType
215     , class = __any_imp::_EnableIfNotAny<_ValueType>
216     >
217   _LIBCPP_INLINE_VISIBILITY
218   any & operator=(_ValueType && __rhs);
219
220   // 6.3.3 any modifiers
221   _LIBCPP_INLINE_VISIBILITY
222   void clear() _NOEXCEPT
223   {
224     if (__h) this->__call(_Action::_Destroy);
225   }
226
227   _LIBCPP_INLINE_VISIBILITY
228   void swap(any & __rhs) _NOEXCEPT;
229
230   // 6.3.4 any observers
231   _LIBCPP_INLINE_VISIBILITY
232   bool empty() const _NOEXCEPT
233   {
234     return __h == nullptr;
235   }
236
237 #if !defined(_LIBCPP_NO_RTTI)
238   _LIBCPP_INLINE_VISIBILITY
239   const type_info & type() const _NOEXCEPT
240   {
241     if (__h) {
242         return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
243     } else {
244         return typeid(void);
245     }
246   }
247 #endif
248
249 private:
250     typedef __any_imp::_Action _Action;
251
252     typedef void* (*_HandleFuncPtr)(_Action, any const *, any *, const type_info *);
253
254     union _Storage
255     {
256         void *  __ptr;
257         __any_imp::_Buffer __buf;
258     };
259
260     _LIBCPP_ALWAYS_INLINE
261     void * __call(_Action __a, any * __other = nullptr,
262                   type_info const * __info = nullptr) const
263     {
264         return __h(__a, this, __other, __info);
265     }
266
267     _LIBCPP_ALWAYS_INLINE
268     void * __call(_Action __a, any * __other = nullptr,
269                   type_info const * __info = nullptr)
270     {
271         return __h(__a, this, __other, __info);
272     }
273
274     template <class>
275     friend struct __any_imp::_SmallHandler;
276     template <class>
277     friend struct __any_imp::_LargeHandler;
278
279     template <class _ValueType>
280     friend typename add_pointer<typename add_const<_ValueType>::type>::type
281     any_cast(any const *) _NOEXCEPT;
282
283     template <class _ValueType>
284     friend typename add_pointer<_ValueType>::type
285     any_cast(any *) _NOEXCEPT;
286
287     _HandleFuncPtr __h;
288     _Storage __s;
289 };
290
291 namespace __any_imp
292 {
293
294   template <class _Tp>
295   struct _LIBCPP_TEMPLATE_VIS _SmallHandler
296   {
297      _LIBCPP_INLINE_VISIBILITY
298      static void* __handle(_Action __act, any const * __this, any * __other,
299                            type_info const * __info)
300      {
301         switch (__act)
302         {
303         case _Action::_Destroy:
304           __destroy(const_cast<any &>(*__this));
305           return nullptr;
306         case _Action::_Copy:
307             __copy(*__this, *__other);
308             return nullptr;
309         case _Action::_Move:
310           __move(const_cast<any &>(*__this), *__other);
311           return nullptr;
312         case _Action::_Get:
313             return __get(const_cast<any &>(*__this), __info);
314         case _Action::_TypeInfo:
315           return __type_info();
316         }
317     }
318
319     template <class _Up>
320     _LIBCPP_INLINE_VISIBILITY
321     static void __create(any & __dest, _Up && __v)
322     {
323         ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Up>(__v));
324         __dest.__h = &_SmallHandler::__handle;
325     }
326
327   private:
328     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
329     static void __destroy(any & __this)
330     {
331         _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
332         __value.~_Tp();
333         __this.__h = nullptr;
334     }
335
336     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
337     static void __copy(any const & __this, any & __dest)
338     {
339         _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
340             static_cast<void const *>(&__this.__s.__buf)));
341     }
342
343     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
344     static void __move(any & __this, any & __dest)
345     {
346         _SmallHandler::__create(__dest, _VSTD::move(
347             *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
348         __destroy(__this);
349     }
350
351     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
352     static void* __get(any & __this, type_info const * __info)
353     {
354 #if !defined(_LIBCPP_NO_RTTI)
355         if (typeid(_Tp) == *__info) {
356             return static_cast<void*>(&__this.__s.__buf);
357         }
358         return nullptr;
359 #else
360         return static_cast<void*>(&__this.__s.__buf);
361 #endif
362     }
363
364     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
365     static void* __type_info()
366     {
367 #if !defined(_LIBCPP_NO_RTTI)
368         return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
369 #else
370         return nullptr;
371 #endif
372     }
373   };
374
375   template <class _Tp>
376   struct _LIBCPP_TEMPLATE_VIS _LargeHandler
377   {
378     _LIBCPP_INLINE_VISIBILITY
379     static void* __handle(_Action __act, any const * __this, any * __other,
380                           type_info const * __info)
381     {
382         switch (__act)
383         {
384         case _Action::_Destroy:
385           __destroy(const_cast<any &>(*__this));
386           return nullptr;
387         case _Action::_Copy:
388           __copy(*__this, *__other);
389           return nullptr;
390         case _Action::_Move:
391           __move(const_cast<any &>(*__this), *__other);
392           return nullptr;
393         case _Action::_Get:
394             return __get(const_cast<any &>(*__this), __info);
395         case _Action::_TypeInfo:
396           return __type_info();
397         }
398     }
399
400     template <class _Up>
401     _LIBCPP_INLINE_VISIBILITY
402     static void __create(any & __dest, _Up && __v)
403     {
404         typedef allocator<_Tp> _Alloc;
405         typedef __allocator_destructor<_Alloc> _Dp;
406         _Alloc __a;
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;
411     }
412
413   private:
414
415     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
416     static void __destroy(any & __this)
417     {
418         delete static_cast<_Tp*>(__this.__s.__ptr);
419         __this.__h = nullptr;
420     }
421
422     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
423     static void __copy(any const & __this, any & __dest)
424     {
425         _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
426     }
427
428     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
429     static void __move(any & __this, any & __dest)
430     {
431       __dest.__s.__ptr = __this.__s.__ptr;
432       __dest.__h = &_LargeHandler::__handle;
433       __this.__h = nullptr;
434     }
435
436     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
437     static void* __get(any & __this, type_info const * __info)
438     {
439 #if !defined(_LIBCPP_NO_RTTI)
440         if (typeid(_Tp) == *__info) {
441             return static_cast<void*>(__this.__s.__ptr);
442         }
443         return nullptr;
444 #else
445         return static_cast<void*>(__this.__s.__ptr);
446 #endif
447     }
448
449     _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
450     static void* __type_info()
451     {
452 #if !defined(_LIBCPP_NO_RTTI)
453         return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
454 #else
455         return nullptr;
456 #endif
457     }
458   };
459
460 } // namespace __any_imp
461
462
463 template <class _ValueType, class>
464 any::any(_ValueType && __v) : __h(nullptr)
465 {
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));
471 }
472
473 template <class _ValueType, class>
474 any & any::operator=(_ValueType && __v)
475 {
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);
480   return *this;
481 }
482
483 inline
484 void any::swap(any & __rhs) _NOEXCEPT
485 {
486     if (__h && __rhs.__h) {
487         any __tmp;
488         __rhs.__call(_Action::_Move, &__tmp);
489         this->__call(_Action::_Move, &__rhs);
490         __tmp.__call(_Action::_Move, this);
491     }
492     else if (__h) {
493         this->__call(_Action::_Move, &__rhs);
494     }
495     else if (__rhs.__h) {
496         __rhs.__call(_Action::_Move, this);
497     }
498 }
499
500 // 6.4 Non-member functions
501
502 inline _LIBCPP_INLINE_VISIBILITY
503 void swap(any & __lhs, any & __rhs) _NOEXCEPT
504 {
505     __lhs.swap(__rhs);
506 }
507
508 template <class _ValueType>
509 _LIBCPP_INLINE_VISIBILITY
510 _ValueType any_cast(any const & __v)
511 {
512     static_assert(
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
517             _Tp;
518     _Tp * __tmp = any_cast<_Tp>(&__v);
519     if (__tmp == nullptr)
520         __throw_bad_any_cast();
521     return *__tmp;
522 }
523
524 template <class _ValueType>
525 _LIBCPP_INLINE_VISIBILITY
526 _ValueType any_cast(any & __v)
527 {
528     static_assert(
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();
536     return *__tmp;
537 }
538
539 template <class _ValueType>
540 _LIBCPP_INLINE_VISIBILITY
541 _ValueType any_cast(any && __v)
542 {
543     static_assert(
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();
551     return *__tmp;
552 }
553
554 template <class _ValueType>
555 inline
556 typename add_pointer<typename add_const<_ValueType>::type>::type
557 any_cast(any const * __any) _NOEXCEPT
558 {
559     static_assert(!is_reference<_ValueType>::value,
560                   "_ValueType may not be a reference.");
561     return any_cast<_ValueType>(const_cast<any *>(__any));
562 }
563
564 template <class _ValueType>
565 typename add_pointer<_ValueType>::type
566 any_cast(any * __any) _NOEXCEPT
567 {
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) {
573
574         return static_cast<_ReturnType>(
575             __any->__call(_Action::_Get, nullptr,
576 #if !defined(_LIBCPP_NO_RTTI)
577                 &typeid(_ValueType)
578 #else
579                 nullptr
580 #endif
581         ));
582
583     }
584     return nullptr;
585 }
586
587 #endif // _LIBCPP_STD_VER > 11
588
589 _LIBCPP_END_NAMESPACE_LFTS
590
591 #endif // _LIBCPP_EXPERIMENTAL_ANY