Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // <experimental/any> -*- C++ -*-
  2.  
  3. // Copyright (C) 2014-2015 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.
  10.  
  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.
  15.  
  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.
  19.  
  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/>.
  24.  
  25. /** @file experimental/any
  26.  *  This is a TS C++ Library header.
  27.  */
  28.  
  29. #ifndef _GLIBCXX_EXPERIMENTAL_ANY
  30. #define _GLIBCXX_EXPERIMENTAL_ANY 1
  31.  
  32. #pragma GCC system_header
  33.  
  34. #if __cplusplus <= 201103L
  35. # include <bits/c++14_warning.h>
  36. #else
  37.  
  38. #include <typeinfo>
  39. #include <new>
  40. #include <utility>
  41. #include <type_traits>
  42.  
  43. namespace std _GLIBCXX_VISIBILITY(default)
  44. {
  45. namespace experimental
  46. {
  47. inline namespace fundamentals_v1
  48. {
  49. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  50.  
  51.   /**
  52.    * @defgroup any Type-safe container of any type
  53.    * @ingroup experimental
  54.    *
  55.    * A type-safe container for single values of value types, as
  56.    * described in n3804 "Any Library Proposal (Revision 3)".
  57.    *
  58.    * @{
  59.    */
  60.  
  61. #define __cpp_lib_experimental_any 201411
  62.  
  63.   /**
  64.    *  @brief Exception class thrown by a failed @c any_cast
  65.    *  @ingroup exceptions
  66.    */
  67.   class bad_any_cast : public bad_cast
  68.   {
  69.   public:
  70.     virtual const char* what() const noexcept { return "bad any_cast"; }
  71.   };
  72.  
  73.   [[gnu::noreturn]] inline void __throw_bad_any_cast()
  74.   {
  75. #if __cpp_exceptions
  76.     throw bad_any_cast{};
  77. #else
  78.     __builtin_abort();
  79. #endif
  80.   }
  81.  
  82.   /**
  83.    *  @brief A type-safe container of any type.
  84.    *
  85.    *  An @c any object's state is either empty or it stores a contained object
  86.    *  of CopyConstructible type.
  87.    */
  88.   class any
  89.   {
  90.     // Holds either pointer to a heap object or the contained object itself.
  91.     union _Storage
  92.     {
  93.       void* _M_ptr;
  94.       std::aligned_storage<sizeof(_M_ptr), sizeof(_M_ptr)>::type _M_buffer;
  95.     };
  96.  
  97.     template<typename _Tp, typename _Safe = is_trivially_copyable<_Tp>,
  98.              bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))>
  99.       using _Internal = std::integral_constant<bool, _Safe::value && _Fits>;
  100.  
  101.     template<typename _Tp>
  102.       struct _Manager_internal; // uses small-object optimization
  103.  
  104.     template<typename _Tp>
  105.       struct _Manager_external; // creates contained object on the heap
  106.  
  107.     template<typename _Tp>
  108.       using _Manager = conditional_t<_Internal<_Tp>::value,
  109.                                      _Manager_internal<_Tp>,
  110.                                      _Manager_external<_Tp>>;
  111.  
  112.     template<typename _Tp, typename _Decayed = decay_t<_Tp>>
  113.       using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
  114.  
  115.   public:
  116.     // construct/destruct
  117.  
  118.     /// Default constructor, creates an empty object.
  119.     any() noexcept : _M_manager(nullptr) { }
  120.  
  121.     /// Copy constructor, copies the state of @p __other
  122.     any(const any& __other) : _M_manager(__other._M_manager)
  123.     {
  124.       if (!__other.empty())
  125.         {
  126.           _Arg __arg;
  127.           __arg._M_any = this;
  128.           _M_manager(_Op_clone, &__other, &__arg);
  129.         }
  130.     }
  131.  
  132.     /**
  133.      * @brief Move constructor, transfer the state from @p __other
  134.      *
  135.      * @post @c __other.empty() (not guaranteed for other implementations)
  136.      */
  137.     any(any&& __other) noexcept
  138.     : _M_manager(__other._M_manager),
  139.       _M_storage(__other._M_storage)
  140.     { __other._M_manager = nullptr; }
  141.  
  142.     /// Construct with a copy of @p __value as the contained object.
  143.     template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
  144.               typename _Mgr = _Manager<_Tp>>
  145.       any(_ValueType&& __value)
  146.       : _M_manager(&_Mgr::_S_manage),
  147.         _M_storage(_Mgr::_S_create(std::forward<_ValueType>(__value)))
  148.       {
  149.         static_assert(is_copy_constructible<_Tp>::value,
  150.                       "The contained object must be CopyConstructible");
  151.       }
  152.  
  153.     /// Destructor, calls @c clear()
  154.     ~any() { clear(); }
  155.  
  156.     // assignments
  157.  
  158.     /// Copy the state of
  159.     any& operator=(const any& __rhs)
  160.     {
  161.       any(__rhs).swap(*this);
  162.       return *this;
  163.     }
  164.  
  165.     /**
  166.      * @brief Move assignment operator
  167.      *
  168.      * @post @c __rhs.empty() (not guaranteed for other implementations)
  169.      */
  170.     any& operator=(any&& __rhs) noexcept
  171.     {
  172.       any(std::move(__rhs)).swap(*this);
  173.       return *this;
  174.     }
  175.  
  176.     /// Store a copy of @p __rhs as the contained object.
  177.     template<typename _ValueType>
  178.       any& operator=(_ValueType&& __rhs)
  179.       {
  180.         any(std::forward<_ValueType>(__rhs)).swap(*this);
  181.         return *this;
  182.       }
  183.  
  184.     // modifiers
  185.  
  186.     /// If not empty, destroy the contained object.
  187.     void clear() noexcept
  188.     {
  189.       if (!empty())
  190.       {
  191.         _M_manager(_Op_destroy, this, nullptr);
  192.         _M_manager = nullptr;
  193.       }
  194.     }
  195.  
  196.     /// Exchange state with another object.
  197.     void swap(any& __rhs) noexcept
  198.     {
  199.       std::swap(_M_manager, __rhs._M_manager);
  200.       std::swap(_M_storage, __rhs._M_storage);
  201.     }
  202.  
  203.     // observers
  204.  
  205.     /// Reports whether there is a contained object or not.
  206.     bool empty() const noexcept { return _M_manager == nullptr; }
  207.  
  208. #if __cpp_rtti
  209.     /// The @c typeid of the contained object, or @c typeid(void) if empty.
  210.     const type_info& type() const noexcept
  211.     {
  212.       if (empty())
  213.         return typeid(void);
  214.       _Arg __arg;
  215.       _M_manager(_Op_get_type_info, this, &__arg);
  216.       return *__arg._M_typeinfo;
  217.     }
  218. #endif
  219.  
  220.     template<typename _Tp>
  221.       static constexpr bool __is_valid_cast()
  222.       { return __or_<is_reference<_Tp>, is_copy_constructible<_Tp>>::value; }
  223.  
  224.   private:
  225.     enum _Op { _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy };
  226.  
  227.     union _Arg
  228.     {
  229.         void* _M_obj;
  230.         const std::type_info* _M_typeinfo;
  231.         any* _M_any;
  232.     };
  233.  
  234.     void (*_M_manager)(_Op, const any*, _Arg*);
  235.     _Storage _M_storage;
  236.  
  237.     template<typename _Tp>
  238.       friend void* __any_caster(const any* __any)
  239.       {
  240.         if (__any->_M_manager != &_Manager<decay_t<_Tp>>::_S_manage)
  241.           return nullptr;
  242.         _Arg __arg;
  243.         __any->_M_manager(_Op_access, __any, &__arg);
  244.         return __arg._M_obj;
  245.       }
  246.  
  247.     // Manage in-place contained object.
  248.     template<typename _Tp>
  249.       struct _Manager_internal
  250.       {
  251.         static void
  252.         _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
  253.  
  254.         template<typename _Up>
  255.           static _Storage
  256.           _S_create(_Up&& __value)
  257.           {
  258.             _Storage __storage;
  259.             void* __addr = &__storage._M_buffer;
  260.             ::new (__addr) _Tp(std::forward<_Up>(__value));
  261.             return __storage;
  262.           }
  263.  
  264.         template<typename _Alloc, typename _Up>
  265.           static _Storage
  266.           _S_alloc(const _Alloc&, _Up&& __value)
  267.           {
  268.             return _S_create(std::forward<_Up>(__value));
  269.           }
  270.       };
  271.  
  272.     // Manage external contained object.
  273.     template<typename _Tp>
  274.       struct _Manager_external
  275.       {
  276.         static void
  277.         _S_manage(_Op __which, const any* __anyp, _Arg* __arg);
  278.  
  279.         template<typename _Up>
  280.           static _Storage
  281.           _S_create(_Up&& __value)
  282.           {
  283.             _Storage __storage;
  284.             __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
  285.             return __storage;
  286.           }
  287.       };
  288.   };
  289.  
  290.   /// Exchange the states of two @c any objects.
  291.   inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
  292.  
  293.   /**
  294.    * @brief Access the contained object.
  295.    *
  296.    * @tparam  _ValueType  A const-reference or CopyConstructible type.
  297.    * @param   __any       The object to access.
  298.    * @return  The contained object.
  299.    * @throw   bad_any_cast If <code>
  300.    *          __any.type() != typeid(remove_reference_t<_ValueType>)
  301.    *          </code>
  302.    */
  303.   template<typename _ValueType>
  304.     inline _ValueType any_cast(const any& __any)
  305.     {
  306.       static_assert(any::__is_valid_cast<_ValueType>(),
  307.           "Template argument must be a reference or CopyConstructible type");
  308.       auto __p = any_cast<add_const_t<remove_reference_t<_ValueType>>>(&__any);
  309.       if (__p)
  310.         return *__p;
  311.       __throw_bad_any_cast();
  312.     }
  313.  
  314.   /**
  315.    * @brief Access the contained object.
  316.    *
  317.    * @tparam  _ValueType  A reference or CopyConstructible type.
  318.    * @param   __any       The object to access.
  319.    * @return  The contained object.
  320.    * @throw   bad_any_cast If <code>
  321.    *          __any.type() != typeid(remove_reference_t<_ValueType>)
  322.    *          </code>
  323.    *
  324.    * @{
  325.    */
  326.   template<typename _ValueType>
  327.     inline _ValueType any_cast(any& __any)
  328.     {
  329.       static_assert(any::__is_valid_cast<_ValueType>(),
  330.           "Template argument must be a reference or CopyConstructible type");
  331.       auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
  332.       if (__p)
  333.         return *__p;
  334.       __throw_bad_any_cast();
  335.     }
  336.  
  337.   template<typename _ValueType>
  338.     inline _ValueType any_cast(any&& __any)
  339.     {
  340.       static_assert(any::__is_valid_cast<_ValueType>(),
  341.           "Template argument must be a reference or CopyConstructible type");
  342.       auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
  343.       if (__p)
  344.         return *__p;
  345.       __throw_bad_any_cast();
  346.     }
  347.   // @}
  348.  
  349.   /**
  350.    * @brief Access the contained object.
  351.    *
  352.    * @tparam  _ValueType  The type of the contained object.
  353.    * @param   __any       A pointer to the object to access.
  354.    * @return  The address of the contained object if <code>
  355.    *          __any != nullptr && __any.type() == typeid(_ValueType)
  356.    *          </code>, otherwise a null pointer.
  357.    *
  358.    * @{
  359.    */
  360.   template<typename _ValueType>
  361.     inline const _ValueType* any_cast(const any* __any) noexcept
  362.     {
  363.       if (__any)
  364.         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
  365.       return nullptr;
  366.     }
  367.  
  368.   template<typename _ValueType>
  369.     inline _ValueType* any_cast(any* __any) noexcept
  370.     {
  371.       if (__any)
  372.         return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
  373.       return nullptr;
  374.     }
  375.   // @}
  376.  
  377.   template<typename _Tp>
  378.     void
  379.     any::_Manager_internal<_Tp>::
  380.     _S_manage(_Op __which, const any* __any, _Arg* __arg)
  381.     {
  382.       // The contained object is in _M_storage._M_buffer
  383.       auto __ptr = reinterpret_cast<const _Tp*>(&__any->_M_storage._M_buffer);
  384.       switch (__which)
  385.       {
  386.       case _Op_access:
  387.         __arg->_M_obj = const_cast<_Tp*>(__ptr);
  388.         break;
  389.       case _Op_get_type_info:
  390. #if __cpp_rtti
  391.         __arg->_M_typeinfo = &typeid(_Tp);
  392. #endif
  393.         break;
  394.       case _Op_clone:
  395.         ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
  396.         break;
  397.       case _Op_destroy:
  398.         __ptr->~_Tp();
  399.         break;
  400.       }
  401.     }
  402.  
  403.   template<typename _Tp>
  404.     void
  405.     any::_Manager_external<_Tp>::
  406.     _S_manage(_Op __which, const any* __any, _Arg* __arg)
  407.     {
  408.       // The contained object is *_M_storage._M_ptr
  409.       auto __ptr = static_cast<const _Tp*>(__any->_M_storage._M_ptr);
  410.       switch (__which)
  411.       {
  412.       case _Op_access:
  413.         __arg->_M_obj = const_cast<_Tp*>(__ptr);
  414.         break;
  415.       case _Op_get_type_info:
  416. #if __cpp_rtti
  417.         __arg->_M_typeinfo = &typeid(_Tp);
  418. #endif
  419.         break;
  420.       case _Op_clone:
  421.         __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr);
  422.         break;
  423.       case _Op_destroy:
  424.         delete __ptr;
  425.         break;
  426.       }
  427.     }
  428.  
  429.   // @} group any
  430. _GLIBCXX_END_NAMESPACE_VERSION
  431. } // namespace fundamentals_v1
  432. } // namespace experimental
  433. } // namespace std
  434.  
  435. #endif // C++14
  436.  
  437. #endif // _GLIBCXX_EXPERIMENTAL_ANY
  438.