xref: /freebsd/contrib/llvm-project/libcxx/include/any (revision 77013d11e6483b970af25e13c9b892075742f7e5)
1// -*- C++ -*-
2//===------------------------------ any -----------------------------------===//
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 <experimental/__config>
84#include <__availability>
85#include <memory>
86#include <typeinfo>
87#include <type_traits>
88#include <cstdlib>
89#include <version>
90
91#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
92#pragma GCC system_header
93#endif
94
95namespace std {
96class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
97{
98public:
99    virtual const char* what() const _NOEXCEPT;
100};
101} // namespace std
102
103_LIBCPP_BEGIN_NAMESPACE_STD
104
105#if _LIBCPP_STD_VER > 14
106
107_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
108_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
109void __throw_bad_any_cast()
110{
111#ifndef _LIBCPP_NO_EXCEPTIONS
112    throw bad_any_cast();
113#else
114    _VSTD::abort();
115#endif
116}
117
118// Forward declarations
119class _LIBCPP_TEMPLATE_VIS any;
120
121template <class _ValueType>
122_LIBCPP_INLINE_VISIBILITY
123add_pointer_t<add_const_t<_ValueType>>
124any_cast(any const *) _NOEXCEPT;
125
126template <class _ValueType>
127_LIBCPP_INLINE_VISIBILITY
128add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT;
129
130namespace __any_imp
131{
132  using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>;
133
134  template <class _Tp>
135  using _IsSmallObject = integral_constant<bool
136        , sizeof(_Tp) <= sizeof(_Buffer)
137          && alignment_of<_Buffer>::value
138             % alignment_of<_Tp>::value == 0
139          && is_nothrow_move_constructible<_Tp>::value
140        >;
141
142  enum class _Action {
143    _Destroy,
144    _Copy,
145    _Move,
146    _Get,
147    _TypeInfo
148  };
149
150  template <class _Tp> struct _SmallHandler;
151  template <class _Tp> struct _LargeHandler;
152
153  template <class _Tp>
154  struct  _LIBCPP_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; };
155  template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id;
156
157  template <class _Tp>
158  inline _LIBCPP_INLINE_VISIBILITY
159  constexpr const void* __get_fallback_typeid() {
160      return &__unique_typeinfo<remove_cv_t<remove_reference_t<_Tp>>>::__id;
161  }
162
163  template <class _Tp>
164  inline _LIBCPP_INLINE_VISIBILITY
165  bool __compare_typeid(type_info const* __id, const void* __fallback_id)
166  {
167#if !defined(_LIBCPP_NO_RTTI)
168      if (__id && *__id == typeid(_Tp))
169          return true;
170#endif
171      if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>())
172          return true;
173      return false;
174  }
175
176  template <class _Tp>
177  using _Handler = conditional_t<
178    _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>;
179
180} // namespace __any_imp
181
182class _LIBCPP_TEMPLATE_VIS any
183{
184public:
185  // construct/destruct
186  _LIBCPP_INLINE_VISIBILITY
187  constexpr any() _NOEXCEPT : __h(nullptr) {}
188
189  _LIBCPP_INLINE_VISIBILITY
190  any(any const & __other) : __h(nullptr)
191  {
192    if (__other.__h) __other.__call(_Action::_Copy, this);
193  }
194
195  _LIBCPP_INLINE_VISIBILITY
196  any(any && __other) _NOEXCEPT : __h(nullptr)
197  {
198    if (__other.__h) __other.__call(_Action::_Move, this);
199  }
200
201  template <
202      class _ValueType
203    , class _Tp = decay_t<_ValueType>
204    , class = enable_if_t<
205        !is_same<_Tp, any>::value &&
206        !__is_inplace_type<_ValueType>::value &&
207        is_copy_constructible<_Tp>::value>
208    >
209  _LIBCPP_INLINE_VISIBILITY
210  any(_ValueType && __value);
211
212  template <class _ValueType, class ..._Args,
213    class _Tp = decay_t<_ValueType>,
214    class = enable_if_t<
215        is_constructible<_Tp, _Args...>::value &&
216        is_copy_constructible<_Tp>::value
217    >
218  >
219  _LIBCPP_INLINE_VISIBILITY
220  explicit any(in_place_type_t<_ValueType>, _Args&&... __args);
221
222  template <class _ValueType, class _Up, class ..._Args,
223    class _Tp = decay_t<_ValueType>,
224    class = enable_if_t<
225        is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value &&
226        is_copy_constructible<_Tp>::value>
227  >
228  _LIBCPP_INLINE_VISIBILITY
229  explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args);
230
231  _LIBCPP_INLINE_VISIBILITY
232  ~any() { this->reset(); }
233
234  // assignments
235  _LIBCPP_INLINE_VISIBILITY
236  any & operator=(any const & __rhs) {
237    any(__rhs).swap(*this);
238    return *this;
239  }
240
241  _LIBCPP_INLINE_VISIBILITY
242  any & operator=(any && __rhs) _NOEXCEPT {
243    any(_VSTD::move(__rhs)).swap(*this);
244    return *this;
245  }
246
247  template <
248      class _ValueType
249    , class _Tp = decay_t<_ValueType>
250    , class = enable_if_t<
251          !is_same<_Tp, any>::value
252          && is_copy_constructible<_Tp>::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  _Tp& 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  _Tp& 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_INLINE_VISIBILITY
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_INLINE_VISIBILITY
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_TEMPLATE_VIS _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 _Tp& __create(any & __dest, _Args&&... __args) {
371        typedef allocator<_Tp> _Alloc;
372        typedef allocator_traits<_Alloc> _ATraits;
373        _Alloc __a;
374        _Tp * __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s.__buf));
375        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
376        __dest.__h = &_SmallHandler::__handle;
377        return *__ret;
378    }
379
380  private:
381    _LIBCPP_INLINE_VISIBILITY
382    static void __destroy(any & __this) {
383        typedef allocator<_Tp> _Alloc;
384        typedef allocator_traits<_Alloc> _ATraits;
385        _Alloc __a;
386        _Tp * __p = static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf));
387        _ATraits::destroy(__a, __p);
388        __this.__h = nullptr;
389    }
390
391    _LIBCPP_INLINE_VISIBILITY
392    static void __copy(any const & __this, any & __dest) {
393        _SmallHandler::__create(__dest, *static_cast<_Tp const *>(
394            static_cast<void const *>(&__this.__s.__buf)));
395    }
396
397    _LIBCPP_INLINE_VISIBILITY
398    static void __move(any & __this, any & __dest) {
399        _SmallHandler::__create(__dest, _VSTD::move(
400            *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf))));
401        __destroy(__this);
402    }
403
404    _LIBCPP_INLINE_VISIBILITY
405    static void* __get(any & __this,
406                       type_info const * __info,
407                       const void* __fallback_id)
408    {
409        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id))
410            return static_cast<void*>(&__this.__s.__buf);
411        return nullptr;
412    }
413
414    _LIBCPP_INLINE_VISIBILITY
415    static void* __type_info()
416    {
417#if !defined(_LIBCPP_NO_RTTI)
418        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
419#else
420        return nullptr;
421#endif
422    }
423  };
424
425  template <class _Tp>
426  struct _LIBCPP_TEMPLATE_VIS _LargeHandler
427  {
428    _LIBCPP_INLINE_VISIBILITY
429    static void* __handle(_Action __act, any const * __this,
430                          any * __other, type_info const * __info,
431                          void const* __fallback_info)
432    {
433        switch (__act)
434        {
435        case _Action::_Destroy:
436          __destroy(const_cast<any &>(*__this));
437          return nullptr;
438        case _Action::_Copy:
439          __copy(*__this, *__other);
440          return nullptr;
441        case _Action::_Move:
442          __move(const_cast<any &>(*__this), *__other);
443          return nullptr;
444        case _Action::_Get:
445            return __get(const_cast<any &>(*__this), __info, __fallback_info);
446        case _Action::_TypeInfo:
447          return __type_info();
448        }
449    }
450
451    template <class ..._Args>
452    _LIBCPP_INLINE_VISIBILITY
453    static _Tp& __create(any & __dest, _Args&&... __args) {
454        typedef allocator<_Tp> _Alloc;
455        typedef allocator_traits<_Alloc> _ATraits;
456        typedef __allocator_destructor<_Alloc> _Dp;
457        _Alloc __a;
458        unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1));
459        _Tp * __ret = __hold.get();
460        _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...);
461        __dest.__s.__ptr = __hold.release();
462        __dest.__h = &_LargeHandler::__handle;
463        return *__ret;
464    }
465
466  private:
467
468    _LIBCPP_INLINE_VISIBILITY
469    static void __destroy(any & __this){
470        typedef allocator<_Tp> _Alloc;
471        typedef allocator_traits<_Alloc> _ATraits;
472        _Alloc __a;
473        _Tp * __p = static_cast<_Tp *>(__this.__s.__ptr);
474        _ATraits::destroy(__a, __p);
475        _ATraits::deallocate(__a, __p, 1);
476        __this.__h = nullptr;
477    }
478
479    _LIBCPP_INLINE_VISIBILITY
480    static void __copy(any const & __this, any & __dest) {
481        _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr));
482    }
483
484    _LIBCPP_INLINE_VISIBILITY
485    static void __move(any & __this, any & __dest) {
486      __dest.__s.__ptr = __this.__s.__ptr;
487      __dest.__h = &_LargeHandler::__handle;
488      __this.__h = nullptr;
489    }
490
491    _LIBCPP_INLINE_VISIBILITY
492    static void* __get(any & __this, type_info const * __info,
493                       void const* __fallback_info)
494    {
495        if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info))
496            return static_cast<void*>(__this.__s.__ptr);
497        return nullptr;
498
499    }
500
501    _LIBCPP_INLINE_VISIBILITY
502    static void* __type_info()
503    {
504#if !defined(_LIBCPP_NO_RTTI)
505        return const_cast<void*>(static_cast<void const *>(&typeid(_Tp)));
506#else
507        return nullptr;
508#endif
509    }
510  };
511
512} // namespace __any_imp
513
514
515template <class _ValueType, class _Tp, class>
516any::any(_ValueType && __v) : __h(nullptr)
517{
518  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v));
519}
520
521template <class _ValueType, class ..._Args, class _Tp, class>
522any::any(in_place_type_t<_ValueType>, _Args&&... __args) {
523  __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
524}
525
526template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
527any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) {
528  __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
529}
530
531template <class _ValueType, class, class>
532inline _LIBCPP_INLINE_VISIBILITY
533any & any::operator=(_ValueType && __v)
534{
535  any(_VSTD::forward<_ValueType>(__v)).swap(*this);
536  return *this;
537}
538
539template <class _ValueType, class ..._Args, class _Tp, class>
540inline _LIBCPP_INLINE_VISIBILITY
541_Tp& any::emplace(_Args&&... __args) {
542  reset();
543  return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...);
544}
545
546template <class _ValueType, class _Up, class ..._Args, class _Tp, class>
547inline _LIBCPP_INLINE_VISIBILITY
548_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) {
549  reset();
550  return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...);
551}
552
553inline _LIBCPP_INLINE_VISIBILITY
554void any::swap(any & __rhs) _NOEXCEPT
555{
556    if (this == &__rhs)
557      return;
558    if (__h && __rhs.__h) {
559        any __tmp;
560        __rhs.__call(_Action::_Move, &__tmp);
561        this->__call(_Action::_Move, &__rhs);
562        __tmp.__call(_Action::_Move, this);
563    }
564    else if (__h) {
565        this->__call(_Action::_Move, &__rhs);
566    }
567    else if (__rhs.__h) {
568        __rhs.__call(_Action::_Move, this);
569    }
570}
571
572// 6.4 Non-member functions
573
574inline _LIBCPP_INLINE_VISIBILITY
575void swap(any & __lhs, any & __rhs) _NOEXCEPT
576{
577    __lhs.swap(__rhs);
578}
579
580template <class _Tp, class ..._Args>
581inline _LIBCPP_INLINE_VISIBILITY
582any make_any(_Args&&... __args) {
583    return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...);
584}
585
586template <class _Tp, class _Up, class ..._Args>
587inline _LIBCPP_INLINE_VISIBILITY
588any make_any(initializer_list<_Up> __il, _Args&&... __args) {
589    return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...);
590}
591
592template <class _ValueType>
593inline _LIBCPP_INLINE_VISIBILITY
594_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
595_ValueType any_cast(any const & __v)
596{
597    using _RawValueType = __uncvref_t<_ValueType>;
598    static_assert(is_constructible<_ValueType, _RawValueType const &>::value,
599                  "ValueType is required to be a const lvalue reference "
600                  "or a CopyConstructible type");
601    auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v);
602    if (__tmp == nullptr)
603        __throw_bad_any_cast();
604    return static_cast<_ValueType>(*__tmp);
605}
606
607template <class _ValueType>
608inline _LIBCPP_INLINE_VISIBILITY
609_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
610_ValueType any_cast(any & __v)
611{
612    using _RawValueType = __uncvref_t<_ValueType>;
613    static_assert(is_constructible<_ValueType, _RawValueType &>::value,
614                  "ValueType is required to be an lvalue reference "
615                  "or a CopyConstructible type");
616    auto __tmp = _VSTD::any_cast<_RawValueType>(&__v);
617    if (__tmp == nullptr)
618        __throw_bad_any_cast();
619    return static_cast<_ValueType>(*__tmp);
620}
621
622template <class _ValueType>
623inline _LIBCPP_INLINE_VISIBILITY
624_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
625_ValueType any_cast(any && __v)
626{
627    using _RawValueType = __uncvref_t<_ValueType>;
628    static_assert(is_constructible<_ValueType, _RawValueType>::value,
629                  "ValueType is required to be an rvalue reference "
630                  "or a CopyConstructible type");
631    auto __tmp = _VSTD::any_cast<_RawValueType>(&__v);
632    if (__tmp == nullptr)
633        __throw_bad_any_cast();
634    return static_cast<_ValueType>(_VSTD::move(*__tmp));
635}
636
637template <class _ValueType>
638inline _LIBCPP_INLINE_VISIBILITY
639add_pointer_t<add_const_t<_ValueType>>
640any_cast(any const * __any) _NOEXCEPT
641{
642    static_assert(!is_reference<_ValueType>::value,
643                  "_ValueType may not be a reference.");
644    return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any));
645}
646
647template <class _RetType>
648inline _LIBCPP_INLINE_VISIBILITY
649_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept {
650  return static_cast<_RetType>(__p);
651}
652
653template <class _RetType>
654inline _LIBCPP_INLINE_VISIBILITY
655_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept {
656  return nullptr;
657}
658
659template <class _ValueType>
660add_pointer_t<_ValueType>
661any_cast(any * __any) _NOEXCEPT
662{
663    using __any_imp::_Action;
664    static_assert(!is_reference<_ValueType>::value,
665                  "_ValueType may not be a reference.");
666    typedef typename add_pointer<_ValueType>::type _ReturnType;
667    if (__any && __any->__h) {
668      void *__p = __any->__call(_Action::_Get, nullptr,
669#if !defined(_LIBCPP_NO_RTTI)
670                          &typeid(_ValueType),
671#else
672                          nullptr,
673#endif
674                          __any_imp::__get_fallback_typeid<_ValueType>());
675        return _VSTD::__pointer_or_func_cast<_ReturnType>(
676            __p, is_function<_ValueType>{});
677    }
678    return nullptr;
679}
680
681#endif // _LIBCPP_STD_VER > 14
682
683_LIBCPP_END_NAMESPACE_STD
684
685#endif // _LIBCPP_ANY
686