For obj-c stage-final re-use the checksum from the previous stage
[official-gcc.git] / libstdc++-v3 / include / std / any
blob21120a9146f9774cdcd76c5c960e1b33bc96cdea
1 // <any> -*- C++ -*-
3 // Copyright (C) 2014-2021 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/any
26  *  This is a Standard C++ Library header.
27  */
29 #ifndef _GLIBCXX_ANY
30 #define _GLIBCXX_ANY 1
32 #pragma GCC system_header
34 #if __cplusplus >= 201703L
36 #include <typeinfo>
37 #include <new>
38 #include <utility>
39 #include <type_traits>
41 namespace std _GLIBCXX_VISIBILITY(default)
43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
45   /**
46    *  @addtogroup utilities
47    *  @{
48    */
50   /**
51    *  @brief Exception class thrown by a failed @c any_cast
52    *  @ingroup exceptions
53    */
54   class bad_any_cast : public bad_cast
55   {
56   public:
57     virtual const char* what() const noexcept { return "bad any_cast"; }
58   };
60   [[gnu::noreturn]] inline void __throw_bad_any_cast()
61   {
62 #if __cpp_exceptions
63     throw bad_any_cast{};
64 #else
65     __builtin_abort();
66 #endif
67   }
69 #define __cpp_lib_any 201606L
71   /**
72    *  @brief A type-safe container of any type.
73    *
74    *  An @c any object's state is either empty or it stores a contained object
75    *  of CopyConstructible type.
76    */
77   class any
78   {
79     // Holds either pointer to a heap object or the contained object itself.
80     union _Storage
81     {
82       constexpr _Storage() : _M_ptr{nullptr} {}
84       // Prevent trivial copies of this type, buffer might hold a non-POD.
85       _Storage(const _Storage&) = delete;
86       _Storage& operator=(const _Storage&) = delete;
88       void* _M_ptr;
89       aligned_storage<sizeof(_M_ptr), alignof(void*)>::type _M_buffer;
90     };
92     template<typename _Tp, typename _Safe = is_nothrow_move_constructible<_Tp>,
93              bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))
94                           && (alignof(_Tp) <= alignof(_Storage))>
95       using _Internal = std::integral_constant<bool, _Safe::value && _Fits>;
97     template<typename _Tp>
98       struct _Manager_internal; // uses small-object optimization
100     template<typename _Tp>
101       struct _Manager_external; // creates contained object on the heap
103     template<typename _Tp>
104       using _Manager = conditional_t<_Internal<_Tp>::value,
105                                      _Manager_internal<_Tp>,
106                                      _Manager_external<_Tp>>;
108     template<typename _Tp, typename _VTp = decay_t<_Tp>>
109       using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>;
111     /// Emplace with an object created from @p __args as the contained object.
112     template <typename _Tp, typename... _Args,
113               typename _Mgr = _Manager<_Tp>>
114       void __do_emplace(_Args&&... __args)
115       {
116         reset();
117         _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
118         _M_manager = &_Mgr::_S_manage;
119       }
121     /// Emplace with an object created from @p __il and @p __args as
122     /// the contained object.
123     template <typename _Tp, typename _Up, typename... _Args,
124               typename _Mgr = _Manager<_Tp>>
125       void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
126       {
127         reset();
128         _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
129         _M_manager = &_Mgr::_S_manage;
130       }
132     template <typename _Res, typename _Tp, typename... _Args>
133       using __any_constructible
134         = enable_if<__and_<is_copy_constructible<_Tp>,
135                            is_constructible<_Tp, _Args...>>::value,
136                     _Res>;
138     template <typename _Tp, typename... _Args>
139       using __any_constructible_t
140         = typename __any_constructible<bool, _Tp, _Args...>::type;
142     template<typename _VTp, typename... _Args>
143       using __emplace_t
144         = typename __any_constructible<_VTp&, _VTp, _Args...>::type;
146   public:
147     // construct/destruct
149     /// Default constructor, creates an empty object.
150     constexpr any() noexcept : _M_manager(nullptr) { }
152     /// Copy constructor, copies the state of @p __other
153     any(const any& __other)
154     {
155       if (!__other.has_value())
156         _M_manager = nullptr;
157       else
158         {
159           _Arg __arg;
160           __arg._M_any = this;
161           __other._M_manager(_Op_clone, &__other, &__arg);
162         }
163     }
165     /**
166      * @brief Move constructor, transfer the state from @p __other
167      *
168      * @post @c !__other.has_value() (this postcondition is a GNU extension)
169      */
170     any(any&& __other) noexcept
171     {
172       if (!__other.has_value())
173         _M_manager = nullptr;
174       else
175         {
176           _Arg __arg;
177           __arg._M_any = this;
178           __other._M_manager(_Op_xfer, &__other, &__arg);
179         }
180     }
182     /// Construct with a copy of @p __value as the contained object.
183     template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>,
184               typename _Mgr = _Manager<_VTp>,
185               enable_if_t<is_copy_constructible<_VTp>::value
186                           && !__is_in_place_type<_VTp>::value, bool> = true>
187       any(_Tp&& __value)
188       : _M_manager(&_Mgr::_S_manage)
189       {
190         _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value));
191       }
193     /// Construct with an object created from @p __args as the contained object.
194     template <typename _Tp, typename... _Args, typename _VTp = decay_t<_Tp>,
195               typename _Mgr = _Manager<_VTp>,
196               __any_constructible_t<_VTp, _Args&&...> = false>
197       explicit
198       any(in_place_type_t<_Tp>, _Args&&... __args)
199       : _M_manager(&_Mgr::_S_manage)
200       {
201         _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
202       }
204     /// Construct with an object created from @p __il and @p __args as
205     /// the contained object.
206     template <typename _Tp, typename _Up, typename... _Args,
207               typename _VTp = decay_t<_Tp>, typename _Mgr = _Manager<_VTp>,
208               __any_constructible_t<_VTp, initializer_list<_Up>,
209                                     _Args&&...> = false>
210       explicit
211       any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args)
212       : _M_manager(&_Mgr::_S_manage)
213       {
214         _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
215       }
217     /// Destructor, calls @c reset()
218     ~any() { reset(); }
220     // assignments
222     /// Copy the state of another object.
223     any&
224     operator=(const any& __rhs)
225     {
226       *this = any(__rhs);
227       return *this;
228     }
230     /**
231      * @brief Move assignment operator
232      *
233      * @post @c !__rhs.has_value() (not guaranteed for other implementations)
234      */
235     any&
236     operator=(any&& __rhs) noexcept
237     {
238       if (!__rhs.has_value())
239         reset();
240       else if (this != &__rhs)
241         {
242           reset();
243           _Arg __arg;
244           __arg._M_any = this;
245           __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
246         }
247       return *this;
248     }
250     /// Store a copy of @p __rhs as the contained object.
251     template<typename _Tp>
252       enable_if_t<is_copy_constructible<_Decay_if_not_any<_Tp>>::value, any&>
253       operator=(_Tp&& __rhs)
254       {
255         *this = any(std::forward<_Tp>(__rhs));
256         return *this;
257       }
259     /// Emplace with an object created from @p __args as the contained object.
260     template <typename _Tp, typename... _Args>
261       __emplace_t<decay_t<_Tp>, _Args...>
262       emplace(_Args&&... __args)
263       {
264         using _VTp = decay_t<_Tp>;
265         __do_emplace<_VTp>(std::forward<_Args>(__args)...);
266         return *any::_Manager<_VTp>::_S_access(_M_storage);
267       }
269     /// Emplace with an object created from @p __il and @p __args as
270     /// the contained object.
271     template <typename _Tp, typename _Up, typename... _Args>
272       __emplace_t<decay_t<_Tp>, initializer_list<_Up>, _Args&&...>
273       emplace(initializer_list<_Up> __il, _Args&&... __args)
274       {
275         using _VTp = decay_t<_Tp>;
276         __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...);
277         return *any::_Manager<_VTp>::_S_access(_M_storage);
278       }
280     // modifiers
282     /// If not empty, destroy the contained object.
283     void reset() noexcept
284     {
285       if (has_value())
286       {
287         _M_manager(_Op_destroy, this, nullptr);
288         _M_manager = nullptr;
289       }
290     }
292     /// Exchange state with another object.
293     void swap(any& __rhs) noexcept
294     {
295       if (!has_value() && !__rhs.has_value())
296         return;
298       if (has_value() && __rhs.has_value())
299         {
300           if (this == &__rhs)
301             return;
303           any __tmp;
304           _Arg __arg;
305           __arg._M_any = &__tmp;
306           __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
307           __arg._M_any = &__rhs;
308           _M_manager(_Op_xfer, this, &__arg);
309           __arg._M_any = this;
310           __tmp._M_manager(_Op_xfer, &__tmp, &__arg);
311         }
312       else
313         {
314           any* __empty = !has_value() ? this : &__rhs;
315           any* __full = !has_value() ? &__rhs : this;
316           _Arg __arg;
317           __arg._M_any = __empty;
318           __full->_M_manager(_Op_xfer, __full, &__arg);
319         }
320     }
322     // observers
324     /// Reports whether there is a contained object or not.
325     bool has_value() const noexcept { return _M_manager != nullptr; }
327 #if __cpp_rtti
328     /// The @c typeid of the contained object, or @c typeid(void) if empty.
329     const type_info& type() const noexcept
330     {
331       if (!has_value())
332         return typeid(void);
333       _Arg __arg;
334       _M_manager(_Op_get_type_info, this, &__arg);
335       return *__arg._M_typeinfo;
336     }
337 #endif
339     template<typename _Tp>
340       static constexpr bool __is_valid_cast()
341       { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
343   private:
344     enum _Op {
345         _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer
346     };
348     union _Arg
349     {
350         void* _M_obj;
351         const std::type_info* _M_typeinfo;
352         any* _M_any;
353     };
355     void (*_M_manager)(_Op, const any*, _Arg*);
356     _Storage _M_storage;
358     template<typename _Tp>
359       friend void* __any_caster(const any* __any);
361     // Manage in-place contained object.
362     template<typename _Tp>
363       struct _Manager_internal
364       {
365         static void
366         _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
368         template<typename _Up>
369           static void
370           _S_create(_Storage& __storage, _Up&& __value)
371           {
372             void* __addr = &__storage._M_buffer;
373             ::new (__addr) _Tp(std::forward<_Up>(__value));
374           }
376         template<typename... _Args>
377           static void
378           _S_create(_Storage& __storage, _Args&&... __args)
379           {
380             void* __addr = &__storage._M_buffer;
381             ::new (__addr) _Tp(std::forward<_Args>(__args)...);
382           }
384         static _Tp*
385         _S_access(const _Storage& __storage)
386         {
387           // The contained object is in __storage._M_buffer
388           const void* __addr = &__storage._M_buffer;
389           return static_cast<_Tp*>(const_cast<void*>(__addr));
390         }
391       };
393     // Manage external contained object.
394     template<typename _Tp>
395       struct _Manager_external
396       {
397         static void
398         _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
400         template<typename _Up>
401           static void
402           _S_create(_Storage& __storage, _Up&& __value)
403           {
404             __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
405           }
406         template<typename... _Args>
407           static void
408           _S_create(_Storage& __storage, _Args&&... __args)
409           {
410             __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
411           }
412         static _Tp*
413         _S_access(const _Storage& __storage)
414         {
415           // The contained object is in *__storage._M_ptr
416           return static_cast<_Tp*>(__storage._M_ptr);
417         }
418       };
419   };
421   /// Exchange the states of two @c any objects.
422   inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
424   /// Create an any holding a @c _Tp constructed from @c __args.
425   template <typename _Tp, typename... _Args>
426     any make_any(_Args&&... __args)
427     {
428       return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
429     }
431   /// Create an any holding a @c _Tp constructed from @c __il and @c __args.
432   template <typename _Tp, typename _Up, typename... _Args>
433     any make_any(initializer_list<_Up> __il, _Args&&... __args)
434     {
435       return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
436     }
438   /**
439    * @brief Access the contained object.
440    *
441    * @tparam  _ValueType  A const-reference or CopyConstructible type.
442    * @param   __any       The object to access.
443    * @return  The contained object.
444    * @throw   bad_any_cast If <code>
445    *          __any.type() != typeid(remove_reference_t<_ValueType>)
446    *          </code>
447    */
448   template<typename _ValueType>
449     inline _ValueType any_cast(const any& __any)
450     {
451       using _Up = __remove_cvref_t<_ValueType>;
452       static_assert(any::__is_valid_cast<_ValueType>(),
453           "Template argument must be a reference or CopyConstructible type");
454       static_assert(is_constructible_v<_ValueType, const _Up&>,
455           "Template argument must be constructible from a const value.");
456       auto __p = any_cast<_Up>(&__any);
457       if (__p)
458         return static_cast<_ValueType>(*__p);
459       __throw_bad_any_cast();
460     }
462   /**
463    * @brief Access the contained object.
464    *
465    * @tparam  _ValueType  A reference or CopyConstructible type.
466    * @param   __any       The object to access.
467    * @return  The contained object.
468    * @throw   bad_any_cast If <code>
469    *          __any.type() != typeid(remove_reference_t<_ValueType>)
470    *          </code>
471    *
472    * @{
473    */
474   template<typename _ValueType>
475     inline _ValueType any_cast(any& __any)
476     {
477       using _Up = __remove_cvref_t<_ValueType>;
478       static_assert(any::__is_valid_cast<_ValueType>(),
479           "Template argument must be a reference or CopyConstructible type");
480       static_assert(is_constructible_v<_ValueType, _Up&>,
481           "Template argument must be constructible from an lvalue.");
482       auto __p = any_cast<_Up>(&__any);
483       if (__p)
484         return static_cast<_ValueType>(*__p);
485       __throw_bad_any_cast();
486     }
488   template<typename _ValueType>
489     inline _ValueType any_cast(any&& __any)
490     {
491       using _Up = __remove_cvref_t<_ValueType>;
492       static_assert(any::__is_valid_cast<_ValueType>(),
493           "Template argument must be a reference or CopyConstructible type");
494       static_assert(is_constructible_v<_ValueType, _Up>,
495           "Template argument must be constructible from an rvalue.");
496       auto __p = any_cast<_Up>(&__any);
497       if (__p)
498         return static_cast<_ValueType>(std::move(*__p));
499       __throw_bad_any_cast();
500     }
501   /// @}
503   /// @cond undocumented
504   template<typename _Tp>
505     void* __any_caster(const any* __any)
506     {
507       // any_cast<T> returns non-null if __any->type() == typeid(T) and
508       // typeid(T) ignores cv-qualifiers so remove them:
509       using _Up = remove_cv_t<_Tp>;
510       // The contained value has a decayed type, so if decay_t<U> is not U,
511       // then it's not possible to have a contained value of type U:
512       if constexpr (!is_same_v<decay_t<_Up>, _Up>)
513         return nullptr;
514       // Only copy constructible types can be used for contained values:
515       else if constexpr (!is_copy_constructible_v<_Up>)
516         return nullptr;
517       // First try comparing function addresses, which works without RTTI
518       else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage
519 #if __cpp_rtti
520           || __any->type() == typeid(_Tp)
521 #endif
522           )
523         {
524           return any::_Manager<_Up>::_S_access(__any->_M_storage);
525         }
526       return nullptr;
527     }
528   /// @endcond
530   /**
531    * @brief Access the contained object.
532    *
533    * @tparam  _ValueType  The type of the contained object.
534    * @param   __any       A pointer to the object to access.
535    * @return  The address of the contained object if <code>
536    *          __any != nullptr && __any.type() == typeid(_ValueType)
537    *          </code>, otherwise a null pointer.
538    *
539    * @{
540    */
541   template<typename _ValueType>
542     inline const _ValueType* any_cast(const any* __any) noexcept
543     {
544       if constexpr (is_object_v<_ValueType>)
545         if (__any)
546           return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
547       return nullptr;
548     }
550   template<typename _ValueType>
551     inline _ValueType* any_cast(any* __any) noexcept
552     {
553       if constexpr (is_object_v<_ValueType>)
554         if (__any)
555           return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
556       return nullptr;
557     }
558   /// @}
560   template<typename _Tp>
561     void
562     any::_Manager_internal<_Tp>::
563     _S_manage(_Op __which, const any* __any, _Arg* __arg)
564     {
565       // The contained object is in _M_storage._M_buffer
566       auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
567       switch (__which)
568       {
569       case _Op_access:
570         __arg->_M_obj = const_cast<_Tp*>(__ptr);
571         break;
572       case _Op_get_type_info:
573 #if __cpp_rtti
574         __arg->_M_typeinfo = &typeid(_Tp);
575 #endif
576         break;
577       case _Op_clone:
578         ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
579         __arg->_M_any->_M_manager = __any->_M_manager;
580         break;
581       case _Op_destroy:
582         __ptr->~_Tp();
583         break;
584       case _Op_xfer:
585         ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
586           (std::move(*const_cast<_Tp*>(__ptr)));
587         __ptr->~_Tp();
588         __arg->_M_any->_M_manager = __any->_M_manager;
589         const_cast<any*>(__any)->_M_manager = nullptr;
590         break;
591       }
592     }
594   template<typename _Tp>
595     void
596     any::_Manager_external<_Tp>::
597     _S_manage(_Op __which, const any* __any, _Arg* __arg)
598     {
599       // The contained object is *_M_storage._M_ptr
600       auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
601       switch (__which)
602       {
603       case _Op_access:
604         __arg->_M_obj = const_cast<_Tp*>(__ptr);
605         break;
606       case _Op_get_type_info:
607 #if __cpp_rtti
608         __arg->_M_typeinfo = &typeid(_Tp);
609 #endif
610         break;
611       case _Op_clone:
612         __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
613         __arg->_M_any->_M_manager = __any->_M_manager;
614         break;
615       case _Op_destroy:
616         delete __ptr;
617         break;
618       case _Op_xfer:
619         __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr;
620         __arg->_M_any->_M_manager = __any->_M_manager;
621         const_cast<any*>(__any)->_M_manager = nullptr;
622         break;
623       }
624     }
626   /// @}
628   namespace __detail::__variant
629   {
630     template<typename> struct _Never_valueless_alt; // see <variant>
632     // Provide the strong exception-safety guarantee when emplacing an
633     // any into a variant.
634     template<>
635       struct _Never_valueless_alt<std::any>
636       : std::true_type
637       { };
638   }  // namespace __detail::__variant
640 _GLIBCXX_END_NAMESPACE_VERSION
641 } // namespace std
643 #endif // C++17
644 #endif // _GLIBCXX_ANY