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