Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // <scoped_allocator> -*- C++ -*-
  2.  
  3. // Copyright (C) 2011-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 include/scoped_allocator
  26.  *  This is a Standard C++ Library header.
  27.  */
  28.  
  29. #ifndef _SCOPED_ALLOCATOR
  30. #define _SCOPED_ALLOCATOR 1
  31.  
  32. #pragma GCC system_header
  33.  
  34. #if __cplusplus < 201103L
  35. # include <bits/c++0x_warning.h>
  36. #else
  37.  
  38. #include <utility>
  39. #include <tuple>
  40. #include <bits/alloc_traits.h>
  41.  
  42. namespace std _GLIBCXX_VISIBILITY(default)
  43. {
  44. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  45.  
  46.   template<template<typename> class _Pred, typename... _Allocs>
  47.     struct __any_of;
  48.  
  49.   template<template<typename> class _Pred, typename _Alloc, typename... _Allocs>
  50.     struct __any_of<_Pred, _Alloc, _Allocs...>
  51.     : __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>>
  52.     { };
  53.  
  54.   template<template<typename> class _Pred, typename _Alloc>
  55.     struct __any_of<_Pred, _Alloc>
  56.     : _Pred<_Alloc>
  57.     { };
  58.  
  59.   /**
  60.    * @addtogroup allocators
  61.    * @{
  62.    */
  63.  
  64.   template<typename _Alloc>
  65.     struct __propagate_on_copy
  66.     : allocator_traits<_Alloc>::propagate_on_container_copy_assignment
  67.     { };
  68.   template<typename _Alloc>
  69.     struct __propagate_on_move
  70.     : allocator_traits<_Alloc>::propagate_on_container_move_assignment
  71.     { };
  72.   template<typename _Alloc>
  73.     struct __propagate_on_swap
  74.     : allocator_traits<_Alloc>::propagate_on_container_swap
  75.     { };
  76.  
  77.  
  78.   template<typename _Alloc>
  79.     inline auto
  80.     __do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator())
  81.     { return __a.outer_allocator(); }
  82.  
  83.   template<typename _Alloc>
  84.     inline _Alloc&
  85.     __do_outermost(_Alloc& __a, ...)
  86.     { return __a; }
  87.  
  88.   // TODO: make recursive (see note in 20.12.4/1)
  89.   template<typename _Alloc>
  90.     inline auto
  91.     __outermost(_Alloc& __a) -> decltype(__do_outermost(__a, &__a))
  92.     { return __do_outermost(__a, &__a); }
  93.  
  94.   template<typename _OuterAlloc, typename... _InnerAllocs>
  95.     class scoped_allocator_adaptor;
  96.  
  97.   template<typename...>
  98.     struct __inner_type_impl;
  99.  
  100.   template<typename _Outer>
  101.     struct __inner_type_impl<_Outer>
  102.     {
  103.       typedef scoped_allocator_adaptor<_Outer> __type;
  104.  
  105.       __inner_type_impl() = default;
  106.       __inner_type_impl(const __inner_type_impl&) = default;
  107.       __inner_type_impl(__inner_type_impl&&) = default;
  108.       __inner_type_impl& operator=(const __inner_type_impl&) = default;
  109.       __inner_type_impl& operator=(__inner_type_impl&&) = default;
  110.      
  111.       template<typename _Alloc>
  112.       __inner_type_impl(const __inner_type_impl<_Alloc>& __other)
  113.       { }
  114.      
  115.       template<typename _Alloc>
  116.       __inner_type_impl(__inner_type_impl<_Alloc>&& __other)
  117.       { }
  118.      
  119.       __type&
  120.       _M_get(__type* __p) noexcept { return *__p; }
  121.  
  122.       const __type&
  123.       _M_get(const __type* __p) const noexcept { return *__p; }
  124.      
  125.       tuple<>
  126.       _M_tie() const noexcept { return tuple<>(); }
  127.      
  128.       bool
  129.       operator==(const __inner_type_impl&) const noexcept
  130.       { return true; }
  131.     };
  132.  
  133.   template<typename _Outer, typename _InnerHead, typename... _InnerTail>
  134.     struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...>
  135.     {
  136.       typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type;
  137.      
  138.       __inner_type_impl() = default;
  139.       __inner_type_impl(const __inner_type_impl&) = default;
  140.       __inner_type_impl(__inner_type_impl&&) = default;
  141.       __inner_type_impl& operator=(const __inner_type_impl&) = default;
  142.       __inner_type_impl& operator=(__inner_type_impl&&) = default;
  143.      
  144.       template<typename... _Allocs>
  145.       __inner_type_impl(const __inner_type_impl<_Allocs...>& __other)
  146.       : _M_inner(__other._M_inner) { }
  147.      
  148.       template<typename... _Allocs>
  149.       __inner_type_impl(__inner_type_impl<_Allocs...>&& __other)
  150.       : _M_inner(std::move(__other._M_inner)) { }
  151.  
  152.     template<typename... _Args>
  153.       explicit
  154.       __inner_type_impl(_Args&&... __args)
  155.       : _M_inner(std::forward<_Args>(__args)...) { }
  156.  
  157.       __type&
  158.       _M_get(void*) noexcept { return _M_inner; }
  159.      
  160.       const __type&
  161.       _M_get(const void*) const noexcept { return _M_inner; }
  162.      
  163.       tuple<const _InnerHead&, const _InnerTail&...>
  164.       _M_tie() const noexcept
  165.       { return _M_inner._M_tie(); }
  166.      
  167.       bool
  168.       operator==(const __inner_type_impl& __other) const noexcept
  169.       { return _M_inner == __other._M_inner; }
  170.      
  171.     private:
  172.       template<typename...> friend class __inner_type_impl;
  173.       template<typename, typename...> friend class scoped_allocator_adaptor;
  174.      
  175.       __type _M_inner;
  176.     };
  177.  
  178.   /// Primary class template.
  179.   template<typename _OuterAlloc, typename... _InnerAllocs>
  180.     class scoped_allocator_adaptor
  181.     : public _OuterAlloc
  182.     {
  183.       typedef allocator_traits<_OuterAlloc> __traits;
  184.  
  185.       typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type;
  186.       __inner_type _M_inner;
  187.  
  188.       template<typename _Outer, typename... _Inner>
  189.         friend class scoped_allocator_adaptor;
  190.  
  191.       template<typename...>
  192.         friend class __inner_type_impl;
  193.  
  194.       tuple<const _OuterAlloc&, const _InnerAllocs&...>
  195.       _M_tie() const noexcept
  196.       { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); }
  197.  
  198.       template<typename _Alloc>
  199.         using __outermost_type = typename
  200.           std::decay<decltype(__outermost(std::declval<_Alloc&>()))>::type;
  201.  
  202.       template<typename _Alloc>
  203.         using __outermost_alloc_traits
  204.           = allocator_traits<__outermost_type<_Alloc>>;
  205.      
  206.       template<typename _Tp, typename... _Args>
  207.         void
  208.         _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args)
  209.         {
  210.           typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
  211.           _O_traits::construct(__outermost(*this), __p,
  212.                                std::forward<_Args>(__args)...);
  213.         }
  214.  
  215.       typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_;
  216.       typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_;
  217.  
  218.       template<typename _Tp, typename... _Args>
  219.         void
  220.         _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args)
  221.         {
  222.           typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
  223.           _O_traits::construct(__outermost(*this), __p,
  224.                                allocator_arg, inner_allocator(),
  225.                                std::forward<_Args>(__args)...);
  226.         }
  227.  
  228.       template<typename _Tp, typename... _Args>
  229.         void
  230.         _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args)
  231.         {
  232.           typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
  233.           _O_traits::construct(__outermost(*this), __p,
  234.                                std::forward<_Args>(__args)...,
  235.                                inner_allocator());
  236.         }
  237.  
  238.       template<typename _Alloc>
  239.         static _Alloc
  240.         _S_select_on_copy(const _Alloc& __a)
  241.         {
  242.           typedef allocator_traits<_Alloc> __a_traits;
  243.           return __a_traits::select_on_container_copy_construction(__a);
  244.         }
  245.  
  246.       template<std::size_t... _Indices>
  247.         scoped_allocator_adaptor(tuple<const _OuterAlloc&,
  248.                                        const _InnerAllocs&...> __refs,
  249.                                  _Index_tuple<_Indices...>)
  250.         : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))),
  251.           _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...)
  252.         { }
  253.  
  254.     public:
  255.       typedef _OuterAlloc                       outer_allocator_type;
  256.       typedef typename __inner_type::__type     inner_allocator_type;
  257.  
  258.       typedef typename __traits::value_type             value_type;
  259.       typedef typename __traits::size_type              size_type;
  260.       typedef typename __traits::difference_type        difference_type;
  261.       typedef typename __traits::pointer                pointer;
  262.       typedef typename __traits::const_pointer          const_pointer;
  263.       typedef typename __traits::void_pointer           void_pointer;
  264.       typedef typename __traits::const_void_pointer     const_void_pointer;
  265.  
  266.       typedef typename conditional<
  267.         __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value,
  268.         true_type, false_type>::type propagate_on_container_copy_assignment;
  269.       typedef typename conditional<
  270.         __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value,
  271.         true_type, false_type>::type propagate_on_container_move_assignment;
  272.       typedef typename conditional<
  273.         __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value,
  274.         true_type, false_type>::type propagate_on_container_swap;
  275.  
  276.       template <class _Tp>
  277.         struct rebind
  278.         {
  279.           typedef scoped_allocator_adaptor<
  280.             typename __traits::template rebind_alloc<_Tp>,
  281.             _InnerAllocs...> other;
  282.         };
  283.  
  284.       scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
  285.  
  286.       template<typename _Outer2>
  287.         scoped_allocator_adaptor(_Outer2&& __outer,
  288.                                  const _InnerAllocs&... __inner)
  289.         : _OuterAlloc(std::forward<_Outer2>(__outer)),
  290.           _M_inner(__inner...)
  291.         { }
  292.  
  293.       scoped_allocator_adaptor(const scoped_allocator_adaptor& __other)
  294.       : _OuterAlloc(__other.outer_allocator()),
  295.         _M_inner(__other._M_inner)
  296.       { }
  297.  
  298.       scoped_allocator_adaptor(scoped_allocator_adaptor&& __other)
  299.       : _OuterAlloc(std::move(__other.outer_allocator())),
  300.         _M_inner(std::move(__other._M_inner))
  301.       { }
  302.  
  303.       template<typename _Outer2>
  304.         scoped_allocator_adaptor(
  305.             const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other)
  306.         : _OuterAlloc(__other.outer_allocator()),
  307.           _M_inner(__other._M_inner)
  308.         { }
  309.  
  310.       template<typename _Outer2>
  311.         scoped_allocator_adaptor(
  312.             scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other)
  313.         : _OuterAlloc(std::move(__other.outer_allocator())),
  314.           _M_inner(std::move(__other._M_inner))
  315.         { }
  316.  
  317.       scoped_allocator_adaptor&
  318.       operator=(const scoped_allocator_adaptor&) = default;
  319.  
  320.       scoped_allocator_adaptor&
  321.       operator=(scoped_allocator_adaptor&&) = default;
  322.  
  323.       inner_allocator_type& inner_allocator() noexcept
  324.       { return _M_inner._M_get(this); }
  325.  
  326.       const inner_allocator_type& inner_allocator() const noexcept
  327.       { return _M_inner._M_get(this); }
  328.  
  329.       outer_allocator_type& outer_allocator() noexcept
  330.       { return static_cast<_OuterAlloc&>(*this); }
  331.  
  332.       const outer_allocator_type& outer_allocator() const noexcept
  333.       { return static_cast<const _OuterAlloc&>(*this); }
  334.  
  335.       pointer allocate(size_type __n)
  336.       { return __traits::allocate(outer_allocator(), __n); }
  337.  
  338.       pointer allocate(size_type __n, const_void_pointer __hint)
  339.       { return __traits::allocate(outer_allocator(), __n, __hint); }
  340.  
  341.       void deallocate(pointer __p, size_type __n)
  342.       { return __traits::deallocate(outer_allocator(), __p, __n); }
  343.  
  344.       size_type max_size() const
  345.       { return __traits::max_size(outer_allocator()); }
  346.  
  347.       template<typename _Tp, typename... _Args>
  348.         void construct(_Tp* __p, _Args&&... __args)
  349.         {
  350.           auto& __inner = inner_allocator();
  351.           auto __use_tag
  352.             = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
  353.           _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
  354.         }
  355.  
  356.       template<typename _T1, typename _T2, typename... _Args1,
  357.                typename... _Args2>
  358.         void
  359.         construct(pair<_T1, _T2>* __p, piecewise_construct_t,
  360.                   tuple<_Args1...> __x, tuple<_Args2...> __y)
  361.         {
  362.           // _GLIBCXX_RESOLVE_LIB_DEFECTS
  363.           // 2203.  wrong argument types for piecewise construction
  364.           auto& __inner = inner_allocator();
  365.           auto __x_use_tag
  366.             = __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner);
  367.           auto __y_use_tag
  368.             = __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner);
  369.           typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
  370.           _O_traits::construct(__outermost(*this), __p, piecewise_construct,
  371.                                _M_construct_p(__x_use_tag, __x),
  372.                                _M_construct_p(__y_use_tag, __y));
  373.         }
  374.  
  375.       template<typename _T1, typename _T2>
  376.         void
  377.         construct(pair<_T1, _T2>* __p)
  378.         { construct(__p, piecewise_construct, tuple<>(), tuple<>()); }
  379.  
  380.       template<typename _T1, typename _T2, typename _Up, typename _Vp>
  381.         void
  382.         construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v)
  383.         {
  384.           construct(__p, piecewise_construct,
  385.                     std::forward_as_tuple(std::forward<_Up>(__u)),
  386.                     std::forward_as_tuple(std::forward<_Vp>(__v)));
  387.         }
  388.  
  389.       template<typename _T1, typename _T2, typename _Up, typename _Vp>
  390.         void
  391.         construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x)
  392.         {
  393.           construct(__p, piecewise_construct,
  394.                     std::forward_as_tuple(__x.first),
  395.                     std::forward_as_tuple(__x.second));
  396.         }
  397.  
  398.       template<typename _T1, typename _T2, typename _Up, typename _Vp>
  399.         void
  400.         construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x)
  401.         {
  402.           construct(__p, piecewise_construct,
  403.                     std::forward_as_tuple(std::forward<_Up>(__x.first)),
  404.                     std::forward_as_tuple(std::forward<_Vp>(__x.second)));
  405.         }
  406.  
  407.       template<typename _Tp>
  408.         void destroy(_Tp* __p)
  409.         {
  410.           typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
  411.           _O_traits::destroy(__outermost(*this), __p);
  412.         }
  413.  
  414.       scoped_allocator_adaptor
  415.       select_on_container_copy_construction() const
  416.       {
  417.         typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type
  418.             _Indices;
  419.         return scoped_allocator_adaptor(_M_tie(), _Indices());
  420.       }
  421.  
  422.       template <typename _OutA1, typename _OutA2, typename... _InA>
  423.       friend bool
  424.       operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
  425.                  const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept;
  426.  
  427.     private:
  428.       template<typename _Tuple>
  429.         _Tuple&&
  430.         _M_construct_p(__uses_alloc0, _Tuple& __t)
  431.         { return std::move(__t); }
  432.  
  433.       template<typename... _Args>
  434.         std::tuple<allocator_arg_t, inner_allocator_type&, _Args...>
  435.         _M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t)
  436.         {
  437.           typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple;
  438.           return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()),
  439.                                 std::move(__t));
  440.         }
  441.  
  442.       template<typename... _Args>
  443.         std::tuple<_Args..., inner_allocator_type&>
  444.         _M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t)
  445.         {
  446.           typedef std::tuple<inner_allocator_type&> _Tuple;
  447.           return std::tuple_cat(std::move(__t), _Tuple(inner_allocator()));
  448.         }
  449.     };
  450.  
  451.   template <typename _OutA1, typename _OutA2, typename... _InA>
  452.     inline bool
  453.     operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
  454.                const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
  455.     {
  456.       return __a.outer_allocator() == __b.outer_allocator()
  457.           && __a._M_inner == __b._M_inner;
  458.     }
  459.  
  460.   template <typename _OutA1, typename _OutA2, typename... _InA>
  461.     inline bool
  462.     operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
  463.                const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
  464.     { return !(__a == __b); }
  465.  
  466.   /// @}
  467.  
  468. _GLIBCXX_END_NAMESPACE_VERSION
  469. } // namespace
  470.  
  471. #endif // C++11
  472.  
  473. #endif // _SCOPED_ALLOCATOR
  474.