xref: /llvm-project-15.0.7/libcxx/include/any (revision 189e52fc)
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_TYPE_VIS_ONLY 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_TYPE_VIS_ONLY __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_TYPE_VIS_ONLY 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  // TODO: Should this be constrained to disallow in_place types like the
245  // ValueType constructor?
246  template <
247      class _ValueType
248    , class _Tp = decay_t<_ValueType>
249    , class = enable_if_t<
250          !is_same<_Tp, any>::value
251          && is_copy_constructible<_Tp>::value
252          && !__is_inplace_type<_ValueType>::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  void 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  void 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
297private:
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_ALWAYS_INLINE
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_ALWAYS_INLINE
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
341namespace __any_imp
342{
343  template <class _Tp>
344  struct _LIBCPP_TYPE_VIS_ONLY _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 void __create(any & __dest, _Args&&... __args) {
371        ::new (static_cast<void*>(&__dest.__s.__buf)) _Tp(_VSTD::forward<_Args>(__args)...);
372        __dest.__h = &_SmallHandler::__handle;
373    }
374
375  private:
376    _LIBCPP_INLINE_VISIBILITY
377    static void __destroy(any & __this) {
378        _Tp & __value = *static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
379        __value.~_Tp();
380        __this.__h = nullptr;
381    }
382
383    _LIBCPP_INLINE_VISIBILITY
384    static void __copy(any const & __this, any & __dest) {
385        _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
386            static_cast<void const *>(&__this.__s.__buf)));
387    }
388
389    _LIBCPP_INLINE_VISIBILITY
390    static void __move(any & __this, any & __dest) {
391        _SmallHandler::__create(__dest, _VSTD::move(
392            *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
393        __destroy(__this);
394    }
395
396    _LIBCPP_INLINE_VISIBILITY
397    static void* __get(any & __this,
398                       type_info const * __info,
399                       const void* __fallback_id)
400    {
401        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
402            return static_cast<void*>(&__this.__s.__buf);
403        return nullptr;
404    }
405
406    _LIBCPP_INLINE_VISIBILITY
407    static void* __type_info()
408    {
409#if !defined(_LIBCPP_NO_RTTI)
410        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
411#else
412        return nullptr;
413#endif
414    }
415  };
416
417  template <class _Tp>
418  struct _LIBCPP_TYPE_VIS_ONLY _LargeHandler
419  {
420    _LIBCPP_INLINE_VISIBILITY
421    static void* __handle(_Action __act, any const * __this,
422                          any * __other, type_info const * __info,
423                          void const* __fallback_info)
424    {
425        switch (__act)
426        {
427        case _Action::_Destroy:
428          __destroy(const_cast<any &>(*__this));
429          return nullptr;
430        case _Action::_Copy:
431          __copy(*__this, *__other);
432          return nullptr;
433        case _Action::_Move:
434          __move(const_cast<any &>(*__this), *__other);
435          return nullptr;
436        case _Action::_Get:
437            return __get(const_cast<any &>(*__this), __info, __fallback_info);
438        case _Action::_TypeInfo:
439          return __type_info();
440        }
441    }
442
443    template <class ..._Args>
444    _LIBCPP_INLINE_VISIBILITY
445    static void __create(any & __dest, _Args&&... __args) {
446        typedef allocator<_Tp> _Alloc;
447        typedef __allocator_destructor<_Alloc> _Dp;
448        _Alloc __a;
449        unique_ptr<_Tp, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
450        ::new ((void*)__hold.get()) _Tp(_VSTD::forward<_Args>(__args)...);
451        __dest.__s.__ptr = __hold.release();
452        __dest.__h = &_LargeHandler::__handle;
453    }
454
455  private:
456
457    _LIBCPP_INLINE_VISIBILITY
458    static void __destroy(any & __this){
459        delete static_cast<_Tp*>(__this.__s.__ptr);
460        __this.__h = nullptr;
461    }
462
463    _LIBCPP_INLINE_VISIBILITY
464    static void __copy(any const & __this, any & __dest) {
465        _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
466    }
467
468    _LIBCPP_INLINE_VISIBILITY
469    static void __move(any & __this, any & __dest) {
470      __dest.__s.__ptr = __this.__s.__ptr;
471      __dest.__h = &_LargeHandler::__handle;
472      __this.__h = nullptr;
473    }
474
475    _LIBCPP_INLINE_VISIBILITY
476    static void* __get(any & __this, type_info const * __info,
477                       void const* __fallback_info)
478    {
479        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
480            return static_cast<void*>(__this.__s.__ptr);
481        return nullptr;
482
483    }
484
485    _LIBCPP_INLINE_VISIBILITY
486    static void* __type_info()
487    {
488#if !defined(_LIBCPP_NO_RTTI)
489        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
490#else
491        return nullptr;
492#endif
493    }
494  };
495
496} // namespace __any_imp
497
498
499template <class _ValueType, class _Tp, class>
500any::any(_ValueType && __v) : __h(nullptr)
501{
502  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v));
503}
504
505template <class _ValueType, class ..._Args, class _Tp, class>
506any::any(in_place_type_t<_ValueType>, _Args&&... __args) {
507  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
508};
509
510template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
511any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {
512  __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
513}
514
515template <class _ValueType, class, class>
516inline _LIBCPP_INLINE_VISIBILITY
517any & any::operator=(_ValueType && __v)
518{
519  any(_VSTD::forward<_ValueType>(__v)).swap(*this);
520  return *this;
521}
522
523template <class _ValueType, class ..._Args, class _Tp, class>
524inline _LIBCPP_INLINE_VISIBILITY
525void any::emplace(_Args&&... __args) {
526  reset();
527  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
528}
529
530template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
531inline _LIBCPP_INLINE_VISIBILITY
532void any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
533  reset();
534  __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
535}
536
537inline _LIBCPP_INLINE_VISIBILITY
538void any::swap(any & __rhs) _NOEXCEPT
539{
540    if (this == &__rhs)
541      return;
542    if (__h && __rhs.__h) {
543        any __tmp;
544        __rhs.__call(_Action::_Move, &__tmp);
545        this->__call(_Action::_Move, &__rhs);
546        __tmp.__call(_Action::_Move, this);
547    }
548    else if (__h) {
549        this->__call(_Action::_Move, &__rhs);
550    }
551    else if (__rhs.__h) {
552        __rhs.__call(_Action::_Move, this);
553    }
554}
555
556// 6.4 Non-member functions
557
558inline _LIBCPP_INLINE_VISIBILITY
559void swap(any & __lhs, any & __rhs) _NOEXCEPT
560{
561    __lhs.swap(__rhs);
562}
563
564template <class _Tp, class ..._Args>
565inline _LIBCPP_INLINE_VISIBILITY
566any make_any(_Args&&... __args) {
567    return any(in_place<_Tp>, _VSTD::forward<_Args>(__args)...);
568}
569
570template <class _Tp, class _Up, class ..._Args>
571inline _LIBCPP_INLINE_VISIBILITY
572any make_any(initializer_list<_Up> __il, _Args&&... __args) {
573    return any(in_place<_Tp>, __il, _VSTD::forward<_Args>(__args)...);
574}
575
576template <class _ValueType>
577inline _LIBCPP_INLINE_VISIBILITY
578_ValueType any_cast(any const & __v)
579{
580    using _RawValueType = __uncvref_t<_ValueType>;
581    static_assert(is_constructible<_ValueType, _RawValueType const &>::value,
582                  "ValueType is required to be a reference or a CopyConstructible type");
583    auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v);
584    if (__tmp == nullptr)
585        __throw_bad_any_cast();
586    return static_cast<_ValueType>(*__tmp);
587}
588
589template <class _ValueType>
590inline _LIBCPP_INLINE_VISIBILITY
591_ValueType any_cast(any & __v)
592{
593    using _RawValueType = __uncvref_t<_ValueType>;
594    static_assert(is_constructible<_ValueType, _RawValueType &>::value,
595                  "ValueType is required to be a reference or a CopyConstructible type");
596    auto __tmp = _VSTD::any_cast<_RawValueType>(&__v);
597    if (__tmp == nullptr)
598        __throw_bad_any_cast();
599    return static_cast<_ValueType>(*__tmp);
600}
601
602template <class _ValueType>
603inline _LIBCPP_INLINE_VISIBILITY
604_ValueType any_cast(any && __v)
605{
606    using _RawValueType = __uncvref_t<_ValueType>;
607    static_assert(is_constructible<_ValueType, _RawValueType>::value,
608                  "ValueType is required to be an rvalue reference 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 _ValueType>
626add_pointer_t<_ValueType>
627any_cast(any * __any) _NOEXCEPT
628{
629    using __any_imp::_Action;
630    static_assert(!is_reference<_ValueType>::value,
631                  "_ValueType may not be a reference.");
632    typedef typename add_pointer<_ValueType>::type _ReturnType;
633    if (__any && __any->__h) {
634        return static_cast<_ReturnType>(
635            __any->__call(_Action::_Get, nullptr,
636#if !defined(_LIBCPP_NO_RTTI)
637                          &typeid(_ValueType),
638#else
639                          nullptr,
640#endif
641                          __any_imp::__get_fallback_typeid<_ValueType>()
642        ));
643    }
644    return nullptr;
645}
646
647#endif // _LIBCPP_STD_VER > 14
648
649_LIBCPP_END_NAMESPACE_STD
650
651#endif // _LIBCPP_ANY
652