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