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