Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // Allocator traits -*- C++ -*-
  2.  
  3. // Copyright (C) 2011-2013 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 bits/alloc_traits.h
  26.  *  This is an internal header file, included by other library headers.
  27.  *  Do not attempt to use it directly. @headername{memory}
  28.  */
  29.  
  30. #ifndef _ALLOC_TRAITS_H
  31. #define _ALLOC_TRAITS_H 1
  32.  
  33. #if __cplusplus >= 201103L
  34.  
  35. #include <bits/memoryfwd.h>
  36. #include <bits/ptr_traits.h>
  37. #include <ext/numeric_traits.h>
  38.  
  39. namespace std _GLIBCXX_VISIBILITY(default)
  40. {
  41. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  42.  
  43.   template<typename _Alloc, typename _Tp>
  44.     class __alloctr_rebind_helper
  45.     {
  46.       template<typename _Alloc2, typename _Tp2>
  47.         static constexpr bool
  48.         _S_chk(typename _Alloc2::template rebind<_Tp2>::other*)
  49.         { return true; }
  50.  
  51.       template<typename, typename>
  52.         static constexpr bool
  53.         _S_chk(...)
  54.         { return false; }
  55.  
  56.     public:
  57.       static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
  58.     };
  59.  
  60.   template<typename _Alloc, typename _Tp>
  61.     const bool __alloctr_rebind_helper<_Alloc, _Tp>::__value;
  62.  
  63.   template<typename _Alloc, typename _Tp,
  64.            bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value>
  65.     struct __alloctr_rebind;
  66.  
  67.   template<typename _Alloc, typename _Tp>
  68.     struct __alloctr_rebind<_Alloc, _Tp, true>
  69.     {
  70.       typedef typename _Alloc::template rebind<_Tp>::other __type;
  71.     };
  72.  
  73.   template<template<typename, typename...> class _Alloc, typename _Tp,
  74.             typename _Up, typename... _Args>
  75.     struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false>
  76.     {
  77.       typedef _Alloc<_Tp, _Args...> __type;
  78.     };
  79.  
  80.   /**
  81.    * @brief  Uniform interface to all allocator types.
  82.    * @ingroup allocators
  83.   */
  84.   template<typename _Alloc>
  85.     struct allocator_traits
  86.     {
  87.       /// The allocator type
  88.       typedef _Alloc allocator_type;
  89.       /// The allocated type
  90.       typedef typename _Alloc::value_type value_type;
  91.  
  92. #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \
  93.   private: \
  94.   template<typename _Tp> \
  95.     static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \
  96.   static _ALT _S_##_NTYPE##_helper(...); \
  97.     typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \
  98.   public:
  99.  
  100. _GLIBCXX_ALLOC_TR_NESTED_TYPE(pointer, value_type*)
  101.  
  102.       /**
  103.        * @brief   The allocator's pointer type.
  104.        *
  105.        * @c Alloc::pointer if that type exists, otherwise @c value_type*
  106.       */
  107.       typedef __pointer pointer;
  108.  
  109. _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_pointer,
  110.   typename pointer_traits<pointer>::template rebind<const value_type>)
  111.  
  112.       /**
  113.        * @brief   The allocator's const pointer type.
  114.        *
  115.        * @c Alloc::const_pointer if that type exists, otherwise
  116.        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
  117.       */
  118.       typedef __const_pointer const_pointer;
  119.  
  120. _GLIBCXX_ALLOC_TR_NESTED_TYPE(void_pointer,
  121.   typename pointer_traits<pointer>::template rebind<void>)
  122.  
  123.       /**
  124.        * @brief   The allocator's void pointer type.
  125.        *
  126.        * @c Alloc::void_pointer if that type exists, otherwise
  127.        * <tt> pointer_traits<pointer>::rebind<void> </tt>
  128.       */
  129.       typedef __void_pointer void_pointer;
  130.  
  131. _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer,
  132.   typename pointer_traits<pointer>::template rebind<const void>)
  133.  
  134.       /**
  135.        * @brief   The allocator's const void pointer type.
  136.        *
  137.        * @c Alloc::const_void_pointer if that type exists, otherwise
  138.        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
  139.       */
  140.       typedef __const_void_pointer const_void_pointer;
  141.  
  142. _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
  143.                               typename pointer_traits<pointer>::difference_type)
  144.  
  145.       /**
  146.        * @brief   The allocator's difference type
  147.        *
  148.        * @c Alloc::difference_type if that type exists, otherwise
  149.        * <tt> pointer_traits<pointer>::difference_type </tt>
  150.       */
  151.       typedef __difference_type difference_type;
  152.  
  153. _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
  154.                               typename make_unsigned<difference_type>::type)
  155.  
  156.       /**
  157.        * @brief   The allocator's size type
  158.        *
  159.        * @c Alloc::size_type if that type exists, otherwise
  160.        * <tt> make_unsigned<difference_type>::type </tt>
  161.       */
  162.       typedef __size_type size_type;
  163.  
  164. _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
  165.                               false_type)
  166.  
  167.       /**
  168.        * @brief   How the allocator is propagated on copy assignment
  169.        *
  170.        * @c Alloc::propagate_on_container_copy_assignment if that type exists,
  171.        * otherwise @c false_type
  172.       */
  173.       typedef __propagate_on_container_copy_assignment
  174.         propagate_on_container_copy_assignment;
  175.  
  176. _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment,
  177.                               false_type)
  178.  
  179.       /**
  180.        * @brief   How the allocator is propagated on move assignment
  181.        *
  182.        * @c Alloc::propagate_on_container_move_assignment if that type exists,
  183.        * otherwise @c false_type
  184.       */
  185.       typedef __propagate_on_container_move_assignment
  186.         propagate_on_container_move_assignment;
  187.  
  188. _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
  189.                               false_type)
  190.  
  191.       /**
  192.        * @brief   How the allocator is propagated on swap
  193.        *
  194.        * @c Alloc::propagate_on_container_swap if that type exists,
  195.        * otherwise @c false_type
  196.       */
  197.       typedef __propagate_on_container_swap propagate_on_container_swap;
  198.  
  199. #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
  200.  
  201.       template<typename _Tp>
  202.         using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
  203.       template<typename _Tp>
  204.         using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
  205.  
  206.     private:
  207.       template<typename _Alloc2>
  208.         struct __allocate_helper
  209.         {
  210.           template<typename _Alloc3,
  211.             typename = decltype(std::declval<_Alloc3*>()->allocate(
  212.                   std::declval<size_type>(),
  213.                   std::declval<const_void_pointer>()))>
  214.             static true_type __test(int);
  215.  
  216.           template<typename>
  217.             static false_type __test(...);
  218.  
  219.           typedef decltype(__test<_Alloc>(0)) type;
  220.           static const bool value = type::value;
  221.         };
  222.  
  223.       template<typename _Alloc2>
  224.         static typename
  225.         enable_if<__allocate_helper<_Alloc2>::value, pointer>::type
  226.         _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint)
  227.         { return __a.allocate(__n, __hint); }
  228.  
  229.       template<typename _Alloc2>
  230.         static typename
  231.         enable_if<!__allocate_helper<_Alloc2>::value, pointer>::type
  232.         _S_allocate(_Alloc2& __a, size_type __n, ...)
  233.         { return __a.allocate(__n); }
  234.  
  235.       template<typename _Tp, typename... _Args>
  236.         struct __construct_helper
  237.         {
  238.           template<typename _Alloc2,
  239.             typename = decltype(std::declval<_Alloc2*>()->construct(
  240.                   std::declval<_Tp*>(), std::declval<_Args>()...))>
  241.             static true_type __test(int);
  242.  
  243.           template<typename>
  244.             static false_type __test(...);
  245.  
  246.           typedef decltype(__test<_Alloc>(0)) type;
  247.           static const bool value = type::value;
  248.         };
  249.  
  250.       template<typename _Tp, typename... _Args>
  251.         static typename
  252.         enable_if<__construct_helper<_Tp, _Args...>::value, void>::type
  253.         _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
  254.         { __a.construct(__p, std::forward<_Args>(__args)...); }
  255.  
  256.       template<typename _Tp, typename... _Args>
  257.         static typename
  258.         enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>,
  259.                          is_constructible<_Tp, _Args...>>::value, void>::type
  260.         _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
  261.         { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
  262.  
  263.       template<typename _Tp>
  264.         struct __destroy_helper
  265.         {
  266.           template<typename _Alloc2,
  267.             typename = decltype(std::declval<_Alloc2*>()->destroy(
  268.                   std::declval<_Tp*>()))>
  269.             static true_type __test(int);
  270.  
  271.           template<typename>
  272.             static false_type __test(...);
  273.  
  274.           typedef decltype(__test<_Alloc>(0)) type;
  275.           static const bool value = type::value;
  276.         };
  277.  
  278.       template<typename _Tp>
  279.         static typename enable_if<__destroy_helper<_Tp>::value, void>::type
  280.         _S_destroy(_Alloc& __a, _Tp* __p)
  281.         { __a.destroy(__p); }
  282.  
  283.       template<typename _Tp>
  284.         static typename enable_if<!__destroy_helper<_Tp>::value, void>::type
  285.         _S_destroy(_Alloc&, _Tp* __p)
  286.         { __p->~_Tp(); }
  287.  
  288.       template<typename _Alloc2>
  289.         struct __maxsize_helper
  290.         {
  291.           template<typename _Alloc3,
  292.             typename = decltype(std::declval<_Alloc3*>()->max_size())>
  293.             static true_type __test(int);
  294.  
  295.           template<typename>
  296.             static false_type __test(...);
  297.  
  298.           typedef decltype(__test<_Alloc2>(0)) type;
  299.           static const bool value = type::value;
  300.         };
  301.  
  302.       template<typename _Alloc2>
  303.         static typename
  304.         enable_if<__maxsize_helper<_Alloc2>::value, size_type>::type
  305.         _S_max_size(_Alloc2& __a)
  306.         { return __a.max_size(); }
  307.  
  308.       template<typename _Alloc2>
  309.         static typename
  310.         enable_if<!__maxsize_helper<_Alloc2>::value, size_type>::type
  311.         _S_max_size(_Alloc2&)
  312.         { return __gnu_cxx::__numeric_traits<size_type>::__max; }
  313.  
  314.       template<typename _Alloc2>
  315.         struct __select_helper
  316.         {
  317.           template<typename _Alloc3, typename
  318.             = decltype(std::declval<_Alloc3*>()
  319.                 ->select_on_container_copy_construction())>
  320.             static true_type __test(int);
  321.  
  322.           template<typename>
  323.             static false_type __test(...);
  324.  
  325.           typedef decltype(__test<_Alloc2>(0)) type;
  326.           static const bool value = type::value;
  327.         };
  328.       template<typename _Alloc2>
  329.         static typename
  330.         enable_if<__select_helper<_Alloc2>::value, _Alloc2>::type
  331.         _S_select(_Alloc2& __a)
  332.         { return __a.select_on_container_copy_construction(); }
  333.  
  334.       template<typename _Alloc2>
  335.         static typename
  336.         enable_if<!__select_helper<_Alloc2>::value, _Alloc2>::type
  337.         _S_select(_Alloc2& __a)
  338.         { return __a; }
  339.  
  340.     public:
  341.  
  342.       /**
  343.        *  @brief  Allocate memory.
  344.        *  @param  __a  An allocator.
  345.        *  @param  __n  The number of objects to allocate space for.
  346.        *
  347.        *  Calls @c a.allocate(n)
  348.       */
  349.       static pointer
  350.       allocate(_Alloc& __a, size_type __n)
  351.       { return __a.allocate(__n); }
  352.  
  353.       /**
  354.        *  @brief  Allocate memory.
  355.        *  @param  __a  An allocator.
  356.        *  @param  __n  The number of objects to allocate space for.
  357.        *  @param  __hint Aid to locality.
  358.        *  @return Memory of suitable size and alignment for @a n objects
  359.        *          of type @c value_type
  360.        *
  361.        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
  362.        *  well-formed, otherwise returns @c a.allocate(n)
  363.       */
  364.       static pointer
  365.       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
  366.       { return _S_allocate(__a, __n, __hint); }
  367.  
  368.       /**
  369.        *  @brief  Deallocate memory.
  370.        *  @param  __a  An allocator.
  371.        *  @param  __p  Pointer to the memory to deallocate.
  372.        *  @param  __n  The number of objects space was allocated for.
  373.        *
  374.        *  Calls <tt> a.deallocate(p, n) </tt>
  375.       */
  376.       static void deallocate(_Alloc& __a, pointer __p, size_type __n)
  377.       { __a.deallocate(__p, __n); }
  378.  
  379.       /**
  380.        *  @brief  Construct an object of type @a _Tp
  381.        *  @param  __a  An allocator.
  382.        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
  383.        *  @param  __args Constructor arguments.
  384.        *
  385.        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
  386.        *  if that expression is well-formed, otherwise uses placement-new
  387.        *  to construct an object of type @a _Tp at location @a __p from the
  388.        *  arguments @a __args...
  389.       */
  390.       template<typename _Tp, typename... _Args>
  391.         static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
  392.         -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
  393.         { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
  394.  
  395.       /**
  396.        *  @brief  Destroy an object of type @a _Tp
  397.        *  @param  __a  An allocator.
  398.        *  @param  __p  Pointer to the object to destroy
  399.        *
  400.        *  Calls @c __a.destroy(__p) if that expression is well-formed,
  401.        *  otherwise calls @c __p->~_Tp()
  402.       */
  403.       template <class _Tp>
  404.         static void destroy(_Alloc& __a, _Tp* __p)
  405.         { _S_destroy(__a, __p); }
  406.  
  407.       /**
  408.        *  @brief  The maximum supported allocation size
  409.        *  @param  __a  An allocator.
  410.        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
  411.        *
  412.        *  Returns @c __a.max_size() if that expression is well-formed,
  413.        *  otherwise returns @c numeric_limits<size_type>::max()
  414.       */
  415.       static size_type max_size(const _Alloc& __a)
  416.       { return _S_max_size(__a); }
  417.  
  418.       /**
  419.        *  @brief  Obtain an allocator to use when copying a container.
  420.        *  @param  __rhs  An allocator.
  421.        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
  422.        *
  423.        *  Returns @c __rhs.select_on_container_copy_construction() if that
  424.        *  expression is well-formed, otherwise returns @a __rhs
  425.       */
  426.       static _Alloc
  427.       select_on_container_copy_construction(const _Alloc& __rhs)
  428.       { return _S_select(__rhs); }
  429.     };
  430.  
  431.   template<typename _Alloc>
  432.   template<typename _Alloc2>
  433.     const bool allocator_traits<_Alloc>::__allocate_helper<_Alloc2>::value;
  434.  
  435.   template<typename _Alloc>
  436.   template<typename _Tp, typename... _Args>
  437.     const bool
  438.     allocator_traits<_Alloc>::__construct_helper<_Tp, _Args...>::value;
  439.  
  440.   template<typename _Alloc>
  441.   template<typename _Tp>
  442.     const bool allocator_traits<_Alloc>::__destroy_helper<_Tp>::value;
  443.  
  444.   template<typename _Alloc>
  445.   template<typename _Alloc2>
  446.     const bool allocator_traits<_Alloc>::__maxsize_helper<_Alloc2>::value;
  447.  
  448.   template<typename _Alloc>
  449.   template<typename _Alloc2>
  450.     const bool allocator_traits<_Alloc>::__select_helper<_Alloc2>::value;
  451.  
  452.   template<typename _Alloc>
  453.     inline void
  454.     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
  455.     { __one = __two; }
  456.  
  457.   template<typename _Alloc>
  458.     inline void
  459.     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
  460.     { }
  461.  
  462.   template<typename _Alloc>
  463.     inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
  464.     {
  465.       typedef allocator_traits<_Alloc> __traits;
  466.       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
  467.       __do_alloc_on_copy(__one, __two, __pocca());
  468.     }
  469.  
  470.   template<typename _Alloc>
  471.     inline _Alloc __alloc_on_copy(const _Alloc& __a)
  472.     {
  473.       typedef allocator_traits<_Alloc> __traits;
  474.       return __traits::select_on_container_copy_construction(__a);
  475.     }
  476.  
  477.   template<typename _Alloc>
  478.     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
  479.     { __one = std::move(__two); }
  480.  
  481.   template<typename _Alloc>
  482.     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
  483.     { }
  484.  
  485.   template<typename _Alloc>
  486.     inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
  487.     {
  488.       typedef allocator_traits<_Alloc> __traits;
  489.       typedef typename __traits::propagate_on_container_move_assignment __pocma;
  490.       __do_alloc_on_move(__one, __two, __pocma());
  491.     }
  492.  
  493.   template<typename _Alloc>
  494.     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
  495.     {
  496.       using std::swap;
  497.       swap(__one, __two);
  498.     }
  499.  
  500.   template<typename _Alloc>
  501.     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
  502.     { }
  503.  
  504.   template<typename _Alloc>
  505.     inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
  506.     {
  507.       typedef allocator_traits<_Alloc> __traits;
  508.       typedef typename __traits::propagate_on_container_swap __pocs;
  509.       __do_alloc_on_swap(__one, __two, __pocs());
  510.     }
  511.  
  512.   template<typename _Alloc>
  513.     class __is_copy_insertable_impl
  514.     {
  515.       typedef allocator_traits<_Alloc> _Traits;
  516.  
  517.       template<typename _Up, typename
  518.                = decltype(_Traits::construct(std::declval<_Alloc&>(),
  519.                                              std::declval<_Up*>(),
  520.                                              std::declval<const _Up&>()))>
  521.         static true_type
  522.         _M_select(int);
  523.  
  524.       template<typename _Up>
  525.         static false_type
  526.         _M_select(...);
  527.  
  528.     public:
  529.       typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
  530.     };
  531.  
  532.   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
  533.   template<typename _Alloc>
  534.     struct __is_copy_insertable
  535.     : __is_copy_insertable_impl<_Alloc>::type
  536.     { };
  537.  
  538.   // std::allocator<_Tp> just requires CopyConstructible
  539.   template<typename _Tp>
  540.     struct __is_copy_insertable<allocator<_Tp>>
  541.     : is_copy_constructible<_Tp>
  542.     { };
  543.  
  544.   // Used to allow copy construction of unordered containers
  545.   template<bool> struct __allow_copy_cons { };
  546.  
  547.   // Used to delete copy constructor of unordered containers
  548.   template<>
  549.     struct __allow_copy_cons<false>
  550.     {
  551.       __allow_copy_cons() = default;
  552.       __allow_copy_cons(const __allow_copy_cons&) = delete;
  553.       __allow_copy_cons(__allow_copy_cons&&) = default;
  554.       __allow_copy_cons& operator=(const __allow_copy_cons&) = default;
  555.       __allow_copy_cons& operator=(__allow_copy_cons&&) = default;
  556.     };
  557.  
  558.   template<typename _Alloc>
  559.     using __check_copy_constructible
  560.       = __allow_copy_cons<__is_copy_insertable<_Alloc>::value>;
  561.  
  562. _GLIBCXX_END_NAMESPACE_VERSION
  563. } // namespace std
  564.  
  565. #endif
  566. #endif
  567.