]>
Commit | Line | Data |
---|---|---|
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->resource()` 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 | |
100 | //! `this->resource()` 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 | container_detail::dispatch_uses_allocator | |
108 | (na, this->resource(), 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 | container_detail::dispatch_uses_allocator\ | |
121 | (na, this->resource(), 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 |