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
17namespace std {
18namespace experimental {
19inline 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
92class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
93{
94public:
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
102void __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
112class any;
113
114template <class _ValueType>
115typename add_pointer<typename add_const<_ValueType>::type>::type
116_LIBCPP_INLINE_VISIBILITY
117any_cast(any const *) _NOEXCEPT;
118
119template <class _ValueType>
120typename add_pointer<_ValueType>::type
121_LIBCPP_INLINE_VISIBILITY
122any_cast(any *) _NOEXCEPT;
123
124namespace __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
167class any
168{
169public:
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
250private:
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
292namespace __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
464template <class _ValueType, class>
465any::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
474template <class _ValueType, class>
475any & 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
484inline
485void 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
503inline _LIBCPP_INLINE_VISIBILITY
504void swap(any & __lhs, any & __rhs) _NOEXCEPT
505{
506    __lhs.swap(__rhs);
507}
508
509template <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
525template <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
540template <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
555template <class _ValueType>
556inline
557typename add_pointer<typename add_const<_ValueType>::type>::type
558any_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
565template <class _ValueType>
566typename add_pointer<_ValueType>::type
567any_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
593