xref: /llvm-project-15.0.7/libcxx/include/any (revision d2baefae)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_ANY
11#define _LIBCPP_ANY
12
13/*
14   any synopsis
15
16namespace std {
17
18  class bad_any_cast : public bad_cast
19  {
20  public:
21    virtual const char* what() const noexcept;
22  };
23
24  class any
25  {
26  public:
27
28    // 6.3.1 any construct/destruct
29    any() noexcept;
30
31    any(const any& other);
32    any(any&& other) noexcept;
33
34    template <class ValueType>
35      any(ValueType&& value);
36
37    ~any();
38
39    // 6.3.2 any assignments
40    any& operator=(const any& rhs);
41    any& operator=(any&& rhs) noexcept;
42
43    template <class ValueType>
44      any& operator=(ValueType&& rhs);
45
46    // 6.3.3 any modifiers
47    template <class ValueType, class... Args>
48      decay_t<ValueType>& emplace(Args&&... args);
49    template <class ValueType, class U, class... Args>
50      decay_t<ValueType>& emplace(initializer_list<U>, Args&&...);
51    void reset() noexcept;
52    void swap(any& rhs) noexcept;
53
54    // 6.3.4 any observers
55    bool has_value() const noexcept;
56    const type_info& type() const noexcept;
57  };
58
59   // 6.4 Non-member functions
60  void swap(any& x, any& y) noexcept;
61
62  template <class T, class ...Args>
63    any make_any(Args&& ...args);
64  template <class T, class U, class ...Args>
65    any make_any(initializer_list<U>, Args&& ...args);
66
67  template<class ValueType>
68    ValueType any_cast(const any& operand);
69  template<class ValueType>
70    ValueType any_cast(any& operand);
71  template<class ValueType>
72    ValueType any_cast(any&& operand);
73
74  template<class ValueType>
75    const ValueType* any_cast(const any* operand) noexcept;
76  template<class ValueType>
77    ValueType* any_cast(any* operand) noexcept;
78
79} // namespace std
80
81*/
82
83#include <__availability>
84#include <__config>
85#include <__utility/forward.h>
86#include <__utility/in_place.h>
87#include <__utility/move.h>
88#include <cstdlib>
89#include <memory>
90#include <type_traits>
91#include <typeinfo>
92#include <version>
93
94#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
95#  pragma GCC system_header
96#endif
97
98namespace std {
99class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
100{
101public:
102    virtual const char* what() const _NOEXCEPT;
103};
104} // namespace std
105
106_LIBCPP_BEGIN_NAMESPACE_STD
107
108#if _LIBCPP_STD_VER > 14
109
110_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
111_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
112void __throw_bad_any_cast()
113{
114#ifndef _LIBCPP_NO_EXCEPTIONS
115    throw bad_any_cast();
116#else
117    _VSTD::abort();
118#endif
119}
120
121// Forward declarations
122class _LIBCPP_TEMPLATE_VIS any;
123
124template <class _ValueType>
125_LIBCPP_INLINE_VISIBILITY
126add_pointer_t<add_const_t<_ValueType>>
127any_cast(any const *) _NOEXCEPT;
128
129template <class _ValueType>
130_LIBCPP_INLINE_VISIBILITY
131add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT;
132
133namespace __any_imp
134{
135  using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>;
136
137  template <class _Tp>
138  using _IsSmallObject = integral_constant<bool
139        , sizeof(_Tp) <= sizeof(_Buffer)
140          && alignment_of<_Buffer>::value
141             % alignment_of<_Tp>::value == 0
142          && is_nothrow_move_constructible<_Tp>::value
143        >;
144
145  enum class _Action {
146    _Destroy,
147    _Copy,
148    _Move,
149    _Get,
150    _TypeInfo
151  };
152
153  template <class _Tp> struct _SmallHandler;
154  template <class _Tp> struct _LargeHandler;
155
156  template <class _Tp>
157  struct  _LIBCPP_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; };
158  template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id;
159
160  template <class _Tp>
161  inline _LIBCPP_INLINE_VISIBILITY
162  constexpr const void* __get_fallback_typeid() {
163      return &__unique_typeinfo<remove_cv_t<remove_reference_t<_Tp>>>::__id;
164  }
165
166  template <class _Tp>
167  inline _LIBCPP_INLINE_VISIBILITY
168  bool __compare_typeid(type_info const* __id, const void* __fallback_id)
169  {
170#if !defined(_LIBCPP_NO_RTTI)
171      if (__id && *__id == typeid(_Tp))
172          return true;
173#endif
174      if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>())
175          return true;
176      return false;
177  }
178
179  template <class _Tp>
180  using _Handler = conditional_t<
181    _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;
182
183} // namespace __any_imp
184
185class _LIBCPP_TEMPLATE_VIS any
186{
187public:
188  // construct/destruct
189  _LIBCPP_INLINE_VISIBILITY
190  constexpr any() _NOEXCEPT : __h(nullptr) {}
191
192  _LIBCPP_INLINE_VISIBILITY
193  any(any const & __other) : __h(nullptr)
194  {
195    if (__other.__h) __other.__call(_Action::_Copy, this);
196  }
197
198  _LIBCPP_INLINE_VISIBILITY
199  any(any && __other) _NOEXCEPT : __h(nullptr)
200  {
201    if (__other.__h) __other.__call(_Action::_Move, this);
202  }
203
204  template <
205      class _ValueType
206    , class _Tp = decay_t<_ValueType>
207    , class = enable_if_t<
208        !is_same<_Tp, any>::value &&
209        !__is_inplace_type<_ValueType>::value &&
210        is_copy_constructible<_Tp>::value>
211    >
212  _LIBCPP_INLINE_VISIBILITY
213  any(_ValueType && __value);
214
215  template <class _ValueType, class ..._Args,
216    class _Tp = decay_t<_ValueType>,
217    class = enable_if_t<
218        is_constructible<_Tp, _Args...>::value &&
219        is_copy_constructible<_Tp>::value
220    >
221  >
222  _LIBCPP_INLINE_VISIBILITY
223  explicit any(in_place_type_t<_ValueType>, _Args&&... __args);
224
225  template <class _ValueType, class _Up, class ..._Args,
226    class _Tp = decay_t<_ValueType>,
227    class = enable_if_t<
228        is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
229        is_copy_constructible<_Tp>::value>
230  >
231  _LIBCPP_INLINE_VISIBILITY
232  explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args);
233
234  _LIBCPP_INLINE_VISIBILITY
235  ~any() { this->reset(); }
236
237  // assignments
238  _LIBCPP_INLINE_VISIBILITY
239  any & operator=(any const & __rhs) {
240    any(__rhs).swap(*this);
241    return *this;
242  }
243
244  _LIBCPP_INLINE_VISIBILITY
245  any & operator=(any && __rhs) _NOEXCEPT {
246    any(_VSTD::move(__rhs)).swap(*this);
247    return *this;
248  }
249
250  template <
251      class _ValueType
252    , class _Tp = decay_t<_ValueType>
253    , class = enable_if_t<
254          !is_same<_Tp, any>::value
255          && is_copy_constructible<_Tp>::value>
256    >
257  _LIBCPP_INLINE_VISIBILITY
258  any & operator=(_ValueType && __rhs);
259
260  template <class _ValueType, class ..._Args,
261    class _Tp = decay_t<_ValueType>,
262    class = enable_if_t<
263        is_constructible<_Tp, _Args...>::value &&
264        is_copy_constructible<_Tp>::value>
265    >
266  _LIBCPP_INLINE_VISIBILITY
267  _Tp& emplace(_Args&&... args);
268
269  template <class _ValueType, class _Up, class ..._Args,
270    class _Tp = decay_t<_ValueType>,
271    class = enable_if_t<
272        is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
273        is_copy_constructible<_Tp>::value>
274  >
275  _LIBCPP_INLINE_VISIBILITY
276  _Tp& emplace(initializer_list<_Up>, _Args&&...);
277
278  // 6.3.3 any modifiers
279  _LIBCPP_INLINE_VISIBILITY
280  void reset() _NOEXCEPT { if (__h) this->__call(_Action::_Destroy); }
281
282  _LIBCPP_INLINE_VISIBILITY
283  void swap(any & __rhs) _NOEXCEPT;
284
285  // 6.3.4 any observers
286  _LIBCPP_INLINE_VISIBILITY
287  bool has_value() const _NOEXCEPT { return __h != nullptr; }
288
289#if !defined(_LIBCPP_NO_RTTI)
290  _LIBCPP_INLINE_VISIBILITY
291  const type_info & type() const _NOEXCEPT {
292    if (__h) {
293        return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo));
294    } else {
295        return typeid(void);
296    }
297  }
298#endif
299
300private:
301    typedef __any_imp::_Action _Action;
302    using _HandleFuncPtr =  void* (*)(_Action, any const *, any *, const type_info *,
303      const void* __fallback_info);
304
305    union _Storage {
306        constexpr _Storage() : __ptr(nullptr) {}
307        void *  __ptr;
308        __any_imp::_Buffer __buf;
309    };
310
311    _LIBCPP_INLINE_VISIBILITY
312    void * __call(_Action __a, any * __other = nullptr,
313                  type_info const * __info = nullptr,
314                   const void* __fallback_info = nullptr) const
315    {
316        return __h(__a, this, __other, __info, __fallback_info);
317    }
318
319    _LIBCPP_INLINE_VISIBILITY
320    void * __call(_Action __a, any * __other = nullptr,
321                  type_info const * __info = nullptr,
322                  const void* __fallback_info = nullptr)
323    {
324        return __h(__a, this, __other, __info, __fallback_info);
325    }
326
327    template <class>
328    friend struct __any_imp::_SmallHandler;
329    template <class>
330    friend struct __any_imp::_LargeHandler;
331
332    template <class _ValueType>
333    friend add_pointer_t<add_const_t<_ValueType>>
334    any_cast(any const *) _NOEXCEPT;
335
336    template <class _ValueType>
337    friend add_pointer_t<_ValueType>
338    any_cast(any *) _NOEXCEPT;
339
340    _HandleFuncPtr __h = nullptr;
341    _Storage __s;
342};
343
344namespace __any_imp
345{
346  template <class _Tp>
347  struct _LIBCPP_TEMPLATE_VIS _SmallHandler
348  {
349     _LIBCPP_INLINE_VISIBILITY
350     static void* __handle(_Action __act, any const * __this, any * __other,
351                           type_info const * __info, const void* __fallback_info)
352     {
353        switch (__act)
354        {
355        case _Action::_Destroy:
356          __destroy(const_cast<any &>(*__this));
357          return nullptr;
358        case _Action::_Copy:
359            __copy(*__this, *__other);
360            return nullptr;
361        case _Action::_Move:
362          __move(const_cast<any &>(*__this), *__other);
363          return nullptr;
364        case _Action::_Get:
365            return __get(const_cast<any &>(*__this), __info, __fallback_info);
366        case _Action::_TypeInfo:
367          return __type_info();
368        }
369    }
370
371    template <class ..._Args>
372    _LIBCPP_INLINE_VISIBILITY
373    static _Tp& __create(any & __dest, _Args&&... __args) {
374        typedef allocator<_Tp> _Alloc;
375        typedef allocator_traits<_Alloc> _ATraits;
376        _Alloc __a;
377        _Tp * __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s.__buf));
378        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
379        __dest.__h = &_SmallHandler::__handle;
380        return *__ret;
381    }
382
383  private:
384    _LIBCPP_INLINE_VISIBILITY
385    static void __destroy(any & __this) {
386        typedef allocator<_Tp> _Alloc;
387        typedef allocator_traits<_Alloc> _ATraits;
388        _Alloc __a;
389        _Tp * __p = static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
390        _ATraits::destroy(__a, __p);
391        __this.__h = nullptr;
392    }
393
394    _LIBCPP_INLINE_VISIBILITY
395    static void __copy(any const & __this, any & __dest) {
396        _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
397            static_cast<void const *>(&__this.__s.__buf)));
398    }
399
400    _LIBCPP_INLINE_VISIBILITY
401    static void __move(any & __this, any & __dest) {
402        _SmallHandler::__create(__dest, _VSTD::move(
403            *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
404        __destroy(__this);
405    }
406
407    _LIBCPP_INLINE_VISIBILITY
408    static void* __get(any & __this,
409                       type_info const * __info,
410                       const void* __fallback_id)
411    {
412        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
413            return static_cast<void*>(&__this.__s.__buf);
414        return nullptr;
415    }
416
417    _LIBCPP_INLINE_VISIBILITY
418    static void* __type_info()
419    {
420#if !defined(_LIBCPP_NO_RTTI)
421        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
422#else
423        return nullptr;
424#endif
425    }
426  };
427
428  template <class _Tp>
429  struct _LIBCPP_TEMPLATE_VIS _LargeHandler
430  {
431    _LIBCPP_INLINE_VISIBILITY
432    static void* __handle(_Action __act, any const * __this,
433                          any * __other, type_info const * __info,
434                          void const* __fallback_info)
435    {
436        switch (__act)
437        {
438        case _Action::_Destroy:
439          __destroy(const_cast<any &>(*__this));
440          return nullptr;
441        case _Action::_Copy:
442          __copy(*__this, *__other);
443          return nullptr;
444        case _Action::_Move:
445          __move(const_cast<any &>(*__this), *__other);
446          return nullptr;
447        case _Action::_Get:
448            return __get(const_cast<any &>(*__this), __info, __fallback_info);
449        case _Action::_TypeInfo:
450          return __type_info();
451        }
452    }
453
454    template <class ..._Args>
455    _LIBCPP_INLINE_VISIBILITY
456    static _Tp& __create(any & __dest, _Args&&... __args) {
457        typedef allocator<_Tp> _Alloc;
458        typedef allocator_traits<_Alloc> _ATraits;
459        typedef __allocator_destructor<_Alloc> _Dp;
460        _Alloc __a;
461        unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1));
462        _Tp * __ret = __hold.get();
463        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
464        __dest.__s.__ptr = __hold.release();
465        __dest.__h = &_LargeHandler::__handle;
466        return *__ret;
467    }
468
469  private:
470
471    _LIBCPP_INLINE_VISIBILITY
472    static void __destroy(any & __this){
473        typedef allocator<_Tp> _Alloc;
474        typedef allocator_traits<_Alloc> _ATraits;
475        _Alloc __a;
476        _Tp * __p = static_cast<_Tp *>(__this.__s.__ptr);
477        _ATraits::destroy(__a, __p);
478        _ATraits::deallocate(__a, __p, 1);
479        __this.__h = nullptr;
480    }
481
482    _LIBCPP_INLINE_VISIBILITY
483    static void __copy(any const & __this, any & __dest) {
484        _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
485    }
486
487    _LIBCPP_INLINE_VISIBILITY
488    static void __move(any & __this, any & __dest) {
489      __dest.__s.__ptr = __this.__s.__ptr;
490      __dest.__h = &_LargeHandler::__handle;
491      __this.__h = nullptr;
492    }
493
494    _LIBCPP_INLINE_VISIBILITY
495    static void* __get(any & __this, type_info const * __info,
496                       void const* __fallback_info)
497    {
498        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
499            return static_cast<void*>(__this.__s.__ptr);
500        return nullptr;
501
502    }
503
504    _LIBCPP_INLINE_VISIBILITY
505    static void* __type_info()
506    {
507#if !defined(_LIBCPP_NO_RTTI)
508        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
509#else
510        return nullptr;
511#endif
512    }
513  };
514
515} // namespace __any_imp
516
517
518template <class _ValueType, class _Tp, class>
519any::any(_ValueType && __v) : __h(nullptr)
520{
521  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v));
522}
523
524template <class _ValueType, class ..._Args, class _Tp, class>
525any::any(in_place_type_t<_ValueType>, _Args&&... __args) {
526  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
527}
528
529template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
530any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {
531  __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
532}
533
534template <class _ValueType, class, class>
535inline _LIBCPP_INLINE_VISIBILITY
536any & any::operator=(_ValueType && __v)
537{
538  any(_VSTD::forward<_ValueType>(__v)).swap(*this);
539  return *this;
540}
541
542template <class _ValueType, class ..._Args, class _Tp, class>
543inline _LIBCPP_INLINE_VISIBILITY
544_Tp& any::emplace(_Args&&... __args) {
545  reset();
546  return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
547}
548
549template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
550inline _LIBCPP_INLINE_VISIBILITY
551_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
552  reset();
553  return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
554}
555
556inline _LIBCPP_INLINE_VISIBILITY
557void any::swap(any & __rhs) _NOEXCEPT
558{
559    if (this == &__rhs)
560      return;
561    if (__h && __rhs.__h) {
562        any __tmp;
563        __rhs.__call(_Action::_Move, &__tmp);
564        this->__call(_Action::_Move, &__rhs);
565        __tmp.__call(_Action::_Move, this);
566    }
567    else if (__h) {
568        this->__call(_Action::_Move, &__rhs);
569    }
570    else if (__rhs.__h) {
571        __rhs.__call(_Action::_Move, this);
572    }
573}
574
575// 6.4 Non-member functions
576
577inline _LIBCPP_INLINE_VISIBILITY
578void swap(any & __lhs, any & __rhs) _NOEXCEPT
579{
580    __lhs.swap(__rhs);
581}
582
583template <class _Tp, class ..._Args>
584inline _LIBCPP_INLINE_VISIBILITY
585any make_any(_Args&&... __args) {
586    return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...);
587}
588
589template <class _Tp, class _Up, class ..._Args>
590inline _LIBCPP_INLINE_VISIBILITY
591any make_any(initializer_list<_Up> __il, _Args&&... __args) {
592    return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...);
593}
594
595template <class _ValueType>
596inline _LIBCPP_INLINE_VISIBILITY
597_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
598_ValueType any_cast(any const & __v)
599{
600    using _RawValueType = __uncvref_t<_ValueType>;
601    static_assert(is_constructible<_ValueType, _RawValueType const &>::value,
602                  "ValueType is required to be a const lvalue reference "
603                  "or a CopyConstructible type");
604    auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v);
605    if (__tmp == nullptr)
606        __throw_bad_any_cast();
607    return static_cast<_ValueType>(*__tmp);
608}
609
610template <class _ValueType>
611inline _LIBCPP_INLINE_VISIBILITY
612_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
613_ValueType any_cast(any & __v)
614{
615    using _RawValueType = __uncvref_t<_ValueType>;
616    static_assert(is_constructible<_ValueType, _RawValueType &>::value,
617                  "ValueType is required to be an lvalue reference "
618                  "or a CopyConstructible type");
619    auto __tmp = _VSTD::any_cast<_RawValueType>(&__v);
620    if (__tmp == nullptr)
621        __throw_bad_any_cast();
622    return static_cast<_ValueType>(*__tmp);
623}
624
625template <class _ValueType>
626inline _LIBCPP_INLINE_VISIBILITY
627_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
628_ValueType any_cast(any && __v)
629{
630    using _RawValueType = __uncvref_t<_ValueType>;
631    static_assert(is_constructible<_ValueType, _RawValueType>::value,
632                  "ValueType is required to be an rvalue reference "
633                  "or a CopyConstructible type");
634    auto __tmp = _VSTD::any_cast<_RawValueType>(&__v);
635    if (__tmp == nullptr)
636        __throw_bad_any_cast();
637    return static_cast<_ValueType>(_VSTD::move(*__tmp));
638}
639
640template <class _ValueType>
641inline _LIBCPP_INLINE_VISIBILITY
642add_pointer_t<add_const_t<_ValueType>>
643any_cast(any const * __any) _NOEXCEPT
644{
645    static_assert(!is_reference<_ValueType>::value,
646                  "_ValueType may not be a reference.");
647    return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any));
648}
649
650template <class _RetType>
651inline _LIBCPP_INLINE_VISIBILITY
652_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept {
653  return static_cast<_RetType>(__p);
654}
655
656template <class _RetType>
657inline _LIBCPP_INLINE_VISIBILITY
658_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept {
659  return nullptr;
660}
661
662template <class _ValueType>
663add_pointer_t<_ValueType>
664any_cast(any * __any) _NOEXCEPT
665{
666    using __any_imp::_Action;
667    static_assert(!is_reference<_ValueType>::value,
668                  "_ValueType may not be a reference.");
669    typedef typename add_pointer<_ValueType>::type _ReturnType;
670    if (__any && __any->__h) {
671      void *__p = __any->__call(_Action::_Get, nullptr,
672#if !defined(_LIBCPP_NO_RTTI)
673                          &typeid(_ValueType),
674#else
675                          nullptr,
676#endif
677                          __any_imp::__get_fallback_typeid<_ValueType>());
678        return _VSTD::__pointer_or_func_cast<_ReturnType>(
679            __p, is_function<_ValueType>{});
680    }
681    return nullptr;
682}
683
684#endif // _LIBCPP_STD_VER > 14
685
686_LIBCPP_END_NAMESPACE_STD
687
688#endif // _LIBCPP_ANY
689