1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP 12 #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP 13 14 #if defined (_MSC_VER) 15 # pragma once 16 #endif 17 18 #include <boost/config.hpp> 19 #include <boost/move/detail/type_traits.hpp> 20 #include <boost/move/utility_core.hpp> 21 #include <boost/container/detail/dispatch_uses_allocator.hpp> 22 #include <boost/container/new_allocator.hpp> 23 #include <boost/container/pmr/memory_resource.hpp> 24 #include <boost/container/pmr/global_resource.hpp> 25 26 #include <cstddef> 27 28 namespace boost { 29 namespace container { 30 namespace pmr { 31 32 //! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements. 33 //! Constructed with different memory resources, different instances of the same specialization of 34 //! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime 35 //! polymorphism allows objects that use polymorphic_allocator to behave as if they used different 36 //! allocator types at run time even though they use the same static allocator type. 37 template <class T> 38 class polymorphic_allocator 39 { 40 public: 41 typedef T value_type; 42 43 //! <b>Effects</b>: Sets m_resource to 44 //! `get_default_resource()`. 45 polymorphic_allocator() BOOST_NOEXCEPT 46 : m_resource(::boost::container::pmr::get_default_resource()) 47 {} 48 49 //! <b>Requires</b>: r is non-null. 50 //! 51 //! <b>Effects</b>: Sets m_resource to r. 52 //! 53 //! <b>Throws</b>: Nothing 54 //! 55 //! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*. 56 //! Non-standard extension: if r is null m_resource is set to get_default_resource(). 57 polymorphic_allocator(memory_resource* r) 58 : m_resource(r ? r : ::boost::container::pmr::get_default_resource()) 59 {} 60 61 //! <b>Effects</b>: Sets m_resource to 62 //! other.resource(). 63 polymorphic_allocator(const polymorphic_allocator& other) 64 : m_resource(other.m_resource) 65 {} 66 67 //! <b>Effects</b>: Sets m_resource to 68 //! other.resource(). 69 template <class U> 70 polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT 71 : m_resource(other.resource()) 72 {} 73 74 //! <b>Effects</b>: Sets m_resource to 75 //! other.resource(). 76 polymorphic_allocator& operator=(const polymorphic_allocator& other) 77 { m_resource = other.m_resource; return *this; } 78 79 //! <b>Returns</b>: Equivalent to 80 //! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`. 81 T* allocate(size_t n) 82 { return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); } 83 84 //! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource, 85 //! using `x.allocate(n * sizeof(T), alignof(T))`. 86 //! 87 //! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)). 88 //! 89 //! <b>Throws</b>: Nothing. 90 void deallocate(T* p, size_t n) 91 { m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); } 92 93 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 94 //! <b>Requires</b>: Uses-allocator construction of T with allocator 95 //! `*this` and constructor arguments `std::forward<Args>(args)...` 96 //! is well-formed. [Note: uses-allocator construction is always well formed for 97 //! types that do not use allocators. - end note] 98 //! 99 //! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator query_yes_no(question, default=False)100 //! `*this` and constructor arguments `std::forward<Args>(args)...`. 101 //! 102 //! <b>Throws</b>: Nothing unless the constructor for T throws. 103 template < typename U, class ...Args> 104 void construct(U* p, BOOST_FWD_REF(Args)...args) 105 { 106 new_allocator<U> na; 107 dtl::dispatch_uses_allocator 108 (na, *this, p, ::boost::forward<Args>(args)...); 109 } 110 111 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 112 113 //Disable this overload if the first argument is pair as some compilers have 114 //overload selection problems when the first parameter is a pair. 115 #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \ 116 template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\ 117 void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\ 118 {\ 119 new_allocator<U> na;\ 120 dtl::dispatch_uses_allocator\ 121 (na, *this, p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\ 122 }\ 123 // 124 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE) 125 #undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE 126 127 #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 128 129 //! <b>Effects</b>: 130 //! p->~U(). 131 template <class U> 132 void destroy(U* p) 133 { (void)p; p->~U(); } 134 135 //! <b>Returns</b>: Equivalent to 136 //! `polymorphic_allocator()`. 137 polymorphic_allocator select_on_container_copy_construction() const 138 { return polymorphic_allocator(); } 139 140 //! <b>Returns</b>: 141 //! m_resource. 142 memory_resource* resource() const 143 { return m_resource; } 144 145 private: 146 memory_resource* m_resource; 147 }; 148 149 //! <b>Returns</b>: 150 //! `*a.resource() == *b.resource()`. 151 template <class T1, class T2> 152 bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT 153 { return *a.resource() == *b.resource(); } 154 155 156 //! <b>Returns</b>: 157 //! `! (a == b)`. 158 template <class T1, class T2> 159 bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT 160 { return *a.resource() != *b.resource(); } 161 162 } //namespace pmr { 163 } //namespace container { 164 } //namespace boost { 165 166 #endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP 167