]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/any
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / any
index 2e8baa6f8dde134d1f40a035ddd593a335dc7f8e..bdad76239b4ada0f59ac519a73d023408bdccf20 100644 (file)
@@ -1,6 +1,6 @@
 // <any> -*- C++ -*-
 
-// Copyright (C) 2014-2016 Free Software Foundation, Inc.
+// Copyright (C) 2014-2022 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 
 #pragma GCC system_header
 
-#if __cplusplus <= 201402L
-# include <bits/c++17_warning.h>
-#else
+#if __cplusplus >= 201703L
 
+#include <initializer_list>
 #include <typeinfo>
 #include <new>
-#include <utility>
 #include <type_traits>
+#include <bits/utility.h> // in_place_type_t
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -68,19 +67,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
   }
 
+#define __cpp_lib_any 201606L
+
   /**
    *  @brief A type-safe container of any type.
-   * 
-   *  An @c any object's state is either empty or it stores a contained object
+   *
+   *  An `any` object's state is either empty or it stores a contained object
    *  of CopyConstructible type.
+   *
+   *  @since C++17
    */
   class any
   {
     // Holds either pointer to a heap object or the contained object itself.
     union _Storage
     {
-      // This constructor intentionally doesn't initialize anything.
-      _Storage() = default;
+      constexpr _Storage() : _M_ptr{nullptr} {}
 
       // Prevent trivial copies of this type, buffer might hold a non-POD.
       _Storage(const _Storage&) = delete;
@@ -102,23 +104,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       struct _Manager_external; // creates contained object on the heap
 
     template<typename _Tp>
-      using _Manager = conditional_t<_Internal<_Tp>::value,
-                                    _Manager_internal<_Tp>,
-                                    _Manager_external<_Tp>>;
+      using _Manager = __conditional_t<_Internal<_Tp>::value,
+                                      _Manager_internal<_Tp>,
+                                      _Manager_external<_Tp>>;
+
+    template<typename _Tp, typename _VTp = decay_t<_Tp>>
+      using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>;
+
+    /// Emplace with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args,
+             typename _Mgr = _Manager<_Tp>>
+      void __do_emplace(_Args&&... __args)
+      {
+       reset();
+        _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+       _M_manager = &_Mgr::_S_manage;
+      }
+
+    /// Emplace with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args,
+             typename _Mgr = _Manager<_Tp>>
+      void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
+      {
+       reset();
+       _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+       _M_manager = &_Mgr::_S_manage;
+      }
+
+    template <typename _Res, typename _Tp, typename... _Args>
+      using __any_constructible
+       = enable_if<__and_<is_copy_constructible<_Tp>,
+                          is_constructible<_Tp, _Args...>>::value,
+                   _Res>;
 
-    template<typename _Tp, typename _Decayed = decay_t<_Tp>>
-      using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
+    template <typename _Tp, typename... _Args>
+      using __any_constructible_t
+       = typename __any_constructible<bool, _Tp, _Args...>::type;
+
+    template<typename _VTp, typename... _Args>
+      using __emplace_t
+       = typename __any_constructible<_VTp&, _VTp, _Args...>::type;
 
   public:
     // construct/destruct
 
     /// Default constructor, creates an empty object.
-    any() noexcept : _M_manager(nullptr) { }
+    constexpr any() noexcept : _M_manager(nullptr) { }
 
     /// Copy constructor, copies the state of @p __other
     any(const any& __other)
     {
-      if (__other.empty())
+      if (!__other.has_value())
        _M_manager = nullptr;
       else
        {
@@ -131,11 +168,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /**
      * @brief Move constructor, transfer the state from @p __other
      *
-     * @post @c __other.empty() (this postcondition is a GNU extension)
+     * @post @c !__other.has_value() (this postcondition is a GNU extension)
      */
     any(any&& __other) noexcept
     {
-      if (__other.empty())
+      if (!__other.has_value())
        _M_manager = nullptr;
       else
        {
@@ -146,65 +183,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
     /// Construct with a copy of @p __value as the contained object.
-    template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
-             typename _Mgr = _Manager<_Tp>,
-              typename enable_if<is_constructible<_Tp, _ValueType&&>::value,
-                                 bool>::type = true>
-      any(_ValueType&& __value)
+    template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>,
+             typename _Mgr = _Manager<_VTp>,
+             typename = _Require<__not_<__is_in_place_type<_VTp>>,
+                                 is_copy_constructible<_VTp>>>
+      any(_Tp&& __value)
       : _M_manager(&_Mgr::_S_manage)
       {
-        _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
-       static_assert(is_copy_constructible<_Tp>::value,
-                     "The contained object must be CopyConstructible");
+       _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value));
       }
 
-    /// Construct with a copy of @p __value as the contained object.
-    template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
-             typename _Mgr = _Manager<_Tp>,
-              typename enable_if<!is_constructible<_Tp, _ValueType&&>::value,
-                                 bool>::type = false>
-      any(_ValueType&& __value)
+    /// Construct with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args, typename _VTp = decay_t<_Tp>,
+             typename _Mgr = _Manager<_VTp>,
+             __any_constructible_t<_VTp, _Args&&...> = false>
+      explicit
+      any(in_place_type_t<_Tp>, _Args&&... __args)
+      : _M_manager(&_Mgr::_S_manage)
+      {
+       _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+      }
+
+    /// Construct with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args,
+             typename _VTp = decay_t<_Tp>, typename _Mgr = _Manager<_VTp>,
+             __any_constructible_t<_VTp, initializer_list<_Up>&,
+                                   _Args&&...> = false>
+      explicit
+      any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args)
       : _M_manager(&_Mgr::_S_manage)
       {
-        _Mgr::_S_create(_M_storage, __value);
-       static_assert(is_copy_constructible<_Tp>::value,
-                     "The contained object must be CopyConstructible");
+       _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
       }
 
-    /// Destructor, calls @c clear()
-    ~any() { clear(); }
+    /// Destructor, calls @c reset()
+    ~any() { reset(); }
 
     // assignments
 
     /// Copy the state of another object.
-    any& operator=(const any& __rhs)
+    any&
+    operator=(const any& __rhs)
     {
-      if (__rhs.empty())
-       clear();
-      else if (this != &__rhs)
-       {
-         if (!empty())
-           _M_manager(_Op_destroy, this, nullptr);
-         _Arg __arg;
-         __arg._M_any = this;
-         __rhs._M_manager(_Op_clone, &__rhs, &__arg);
-       }
+      *this = any(__rhs);
       return *this;
     }
 
     /**
      * @brief Move assignment operator
      *
-     * @post @c __rhs.empty() (not guaranteed for other implementations)
+     * @post @c !__rhs.has_value() (not guaranteed for other implementations)
      */
-    any& operator=(any&& __rhs) noexcept
+    any&
+    operator=(any&& __rhs) noexcept
     {
-      if (__rhs.empty())
-       clear();
+      if (!__rhs.has_value())
+       reset();
       else if (this != &__rhs)
        {
-         if (!empty())
-           _M_manager(_Op_destroy, this, nullptr);
+         reset();
          _Arg __arg;
          __arg._M_any = this;
          __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
@@ -213,20 +251,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
     /// Store a copy of @p __rhs as the contained object.
-    template<typename _ValueType>
-      enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&>
-      operator=(_ValueType&& __rhs)
+    template<typename _Tp>
+      enable_if_t<is_copy_constructible<_Decay_if_not_any<_Tp>>::value, any&>
+      operator=(_Tp&& __rhs)
       {
-       *this = any(std::forward<_ValueType>(__rhs));
+       *this = any(std::forward<_Tp>(__rhs));
        return *this;
       }
 
+    /// Emplace with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args>
+      __emplace_t<decay_t<_Tp>, _Args...>
+      emplace(_Args&&... __args)
+      {
+       using _VTp = decay_t<_Tp>;
+       __do_emplace<_VTp>(std::forward<_Args>(__args)...);
+       return *any::_Manager<_VTp>::_S_access(_M_storage);
+      }
+
+    /// Emplace with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args>
+      __emplace_t<decay_t<_Tp>, initializer_list<_Up>&, _Args&&...>
+      emplace(initializer_list<_Up> __il, _Args&&... __args)
+      {
+       using _VTp = decay_t<_Tp>;
+       __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...);
+       return *any::_Manager<_VTp>::_S_access(_M_storage);
+      }
+
     // modifiers
 
     /// If not empty, destroy the contained object.
-    void clear() noexcept
+    void reset() noexcept
     {
-      if (!empty())
+      if (has_value())
       {
        _M_manager(_Op_destroy, this, nullptr);
        _M_manager = nullptr;
@@ -236,10 +295,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /// Exchange state with another object.
     void swap(any& __rhs) noexcept
     {
-      if (empty() && __rhs.empty())
+      if (!has_value() && !__rhs.has_value())
        return;
 
-      if (!empty() && !__rhs.empty())
+      if (has_value() && __rhs.has_value())
        {
          if (this == &__rhs)
            return;
@@ -255,8 +314,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       else
        {
-         any* __empty = empty() ? this : &__rhs;
-         any* __full = empty() ? &__rhs : this;
+         any* __empty = !has_value() ? this : &__rhs;
+         any* __full = !has_value() ? &__rhs : this;
          _Arg __arg;
          __arg._M_any = __empty;
          __full->_M_manager(_Op_xfer, __full, &__arg);
@@ -266,13 +325,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     // observers
 
     /// Reports whether there is a contained object or not.
-    bool empty() const noexcept { return _M_manager == nullptr; }
+    bool has_value() const noexcept { return _M_manager != nullptr; }
 
 #if __cpp_rtti
     /// The @c typeid of the contained object, or @c typeid(void) if empty.
     const type_info& type() const noexcept
     {
-      if (empty())
+      if (!has_value())
        return typeid(void);
       _Arg __arg;
       _M_manager(_Op_get_type_info, this, &__arg);
@@ -280,9 +339,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 #endif
 
+    /// @cond undocumented
     template<typename _Tp>
       static constexpr bool __is_valid_cast()
       { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
+    /// @endcond
 
   private:
     enum _Op {
@@ -299,8 +360,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void (*_M_manager)(_Op, const any*, _Arg*);
     _Storage _M_storage;
 
+    /// @cond undocumented
     template<typename _Tp>
       friend void* __any_caster(const any* __any);
+    /// @endcond
 
     // Manage in-place contained object.
     template<typename _Tp>
@@ -316,6 +379,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            void* __addr = &__storage._M_buffer;
            ::new (__addr) _Tp(std::forward<_Up>(__value));
          }
+
+       template<typename... _Args>
+         static void
+         _S_create(_Storage& __storage, _Args&&... __args)
+         {
+           void* __addr = &__storage._M_buffer;
+           ::new (__addr) _Tp(std::forward<_Args>(__args)...);
+         }
+
+       static _Tp*
+       _S_access(const _Storage& __storage)
+       {
+         // The contained object is in __storage._M_buffer
+         const void* __addr = &__storage._M_buffer;
+         return static_cast<_Tp*>(const_cast<void*>(__addr));
+       }
       };
 
     // Manage external contained object.
@@ -331,12 +410,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          {
            __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
          }
+       template<typename... _Args>
+         static void
+         _S_create(_Storage& __storage, _Args&&... __args)
+         {
+           __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
+         }
+       static _Tp*
+       _S_access(const _Storage& __storage)
+       {
+         // The contained object is in *__storage._M_ptr
+         return static_cast<_Tp*>(__storage._M_ptr);
+       }
       };
   };
 
   /// Exchange the states of two @c any objects.
   inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
 
+  /// Create an `any` holding a `_Tp` constructed from `__args...`.
+  template <typename _Tp, typename... _Args>
+    inline
+    enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>, _Args...>, any>
+    make_any(_Args&&... __args)
+    {
+      return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
+    }
+
+  /// Create an `any` holding a `_Tp` constructed from `__il` and `__args...`.
+  template <typename _Tp, typename _Up, typename... _Args>
+    inline
+    enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>,
+                                  initializer_list<_Up>&, _Args...>, any>
+    make_any(initializer_list<_Up> __il, _Args&&... __args)
+    {
+      return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
+    }
+
   /**
    * @brief Access the contained object.
    *
@@ -350,11 +460,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _ValueType>
     inline _ValueType any_cast(const any& __any)
     {
+      using _Up = __remove_cvref_t<_ValueType>;
       static_assert(any::__is_valid_cast<_ValueType>(),
          "Template argument must be a reference or CopyConstructible type");
-      auto __p = any_cast<add_const_t<remove_reference_t<_ValueType>>>(&__any);
+      static_assert(is_constructible_v<_ValueType, const _Up&>,
+         "Template argument must be constructible from a const value.");
+      auto __p = any_cast<_Up>(&__any);
       if (__p)
-       return *__p;
+       return static_cast<_ValueType>(*__p);
       __throw_bad_any_cast();
     }
 
@@ -373,52 +486,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _ValueType>
     inline _ValueType any_cast(any& __any)
     {
+      using _Up = __remove_cvref_t<_ValueType>;
       static_assert(any::__is_valid_cast<_ValueType>(),
          "Template argument must be a reference or CopyConstructible type");
-      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
-      if (__p)
-       return *__p;
-      __throw_bad_any_cast();
-    }
-
-  template<typename _ValueType,
-           typename enable_if<!is_move_constructible<_ValueType>::value
-                              || is_lvalue_reference<_ValueType>::value,
-                              bool>::type = true>
-    inline _ValueType any_cast(any&& __any)
-    {
-      static_assert(any::__is_valid_cast<_ValueType>(),
-         "Template argument must be a reference or CopyConstructible type");
-      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
+      static_assert(is_constructible_v<_ValueType, _Up&>,
+         "Template argument must be constructible from an lvalue.");
+      auto __p = any_cast<_Up>(&__any);
       if (__p)
-       return *__p;
+       return static_cast<_ValueType>(*__p);
       __throw_bad_any_cast();
     }
 
-  template<typename _ValueType,
-           typename enable_if<is_move_constructible<_ValueType>::value
-                              && !is_lvalue_reference<_ValueType>::value,
-                              bool>::type = false>
+  template<typename _ValueType>
     inline _ValueType any_cast(any&& __any)
     {
+      using _Up = __remove_cvref_t<_ValueType>;
       static_assert(any::__is_valid_cast<_ValueType>(),
          "Template argument must be a reference or CopyConstructible type");
-      auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
+      static_assert(is_constructible_v<_ValueType, _Up>,
+         "Template argument must be constructible from an rvalue.");
+      auto __p = any_cast<_Up>(&__any);
       if (__p)
-       return std::move(*__p);
+       return static_cast<_ValueType>(std::move(*__p));
       __throw_bad_any_cast();
     }
-  // @}
+  /// @}
 
+  /// @cond undocumented
   template<typename _Tp>
     void* __any_caster(const any* __any)
     {
-      if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage)
+      // any_cast<T> returns non-null if __any->type() == typeid(T) and
+      // typeid(T) ignores cv-qualifiers so remove them:
+      using _Up = remove_cv_t<_Tp>;
+      // The contained value has a decayed type, so if decay_t<U> is not U,
+      // then it's not possible to have a contained value of type U:
+      if constexpr (!is_same_v<decay_t<_Up>, _Up>)
        return nullptr;
-      any::_Arg __arg;
-      __any->_M_manager(any::_Op_access, __any, &__arg);
-      return __arg._M_obj;
+      // Only copy constructible types can be used for contained values:
+      else if constexpr (!is_copy_constructible_v<_Up>)
+       return nullptr;
+      // First try comparing function addresses, which works without RTTI
+      else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage
+#if __cpp_rtti
+         || __any->type() == typeid(_Tp)
+#endif
+         )
+       {
+         return any::_Manager<_Up>::_S_access(__any->_M_storage);
+       }
+      return nullptr;
     }
+  /// @endcond
 
   /**
    * @brief Access the contained object.
@@ -434,19 +553,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _ValueType>
     inline const _ValueType* any_cast(const any* __any) noexcept
     {
-      if (__any)
-       return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
+      if constexpr (is_object_v<_ValueType>)
+       if (__any)
+         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
       return nullptr;
     }
 
   template<typename _ValueType>
     inline _ValueType* any_cast(any* __any) noexcept
     {
-      if (__any)
-       return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
+      if constexpr (is_object_v<_ValueType>)
+       if (__any)
+         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
       return nullptr;
     }
-  // @}
+  /// @}
 
   template<typename _Tp>
     void
@@ -473,7 +594,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __ptr->~_Tp();
        break;
       case _Op_xfer:
-       ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
+       ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
+         (std::move(*const_cast<_Tp*>(__ptr)));
        __ptr->~_Tp();
        __arg->_M_any->_M_manager = __any->_M_manager;
        const_cast<any*>(__any)->_M_manager = nullptr;
@@ -514,10 +636,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   /// @}
-  
+
+  namespace __detail::__variant
+  {
+    template<typename> struct _Never_valueless_alt; // see <variant>
+
+    // Provide the strong exception-safety guarantee when emplacing an
+    // any into a variant.
+    template<>
+      struct _Never_valueless_alt<std::any>
+      : std::true_type
+      { };
+  }  // namespace __detail::__variant
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
-#endif // C++14
-
+#endif // C++17
 #endif // _GLIBCXX_ANY