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