1 /*
2 Copyright 2019 Glen Joseph Fernandes
3 (glenjofe@gmail.com)
4
5 Distributed under the Boost Software License, Version 1.0.
6 (http://www.boost.org/LICENSE_1_0.txt)
7 */
8 #ifndef BOOST_CORE_ALLOC_CONSTRUCT_HPP
9 #define BOOST_CORE_ALLOC_CONSTRUCT_HPP
10
11 #include <boost/core/noinit_adaptor.hpp>
12
13 namespace boost {
14
15 template<class A, class T>
16 inline void
alloc_destroy(A & a,T * p)17 alloc_destroy(A& a, T* p)
18 {
19 boost::allocator_destroy(a, p);
20 }
21
22 template<class A, class T>
23 inline void
alloc_destroy_n(A & a,T * p,std::size_t n)24 alloc_destroy_n(A& a, T* p, std::size_t n)
25 {
26 while (n > 0) {
27 boost::allocator_destroy(a, p + --n);
28 }
29 }
30
31 template<class A, class T>
32 inline void
alloc_destroy(noinit_adaptor<A> &,T * p)33 alloc_destroy(noinit_adaptor<A>&, T* p)
34 {
35 p->~T();
36 }
37
38 template<class A, class T>
39 inline void
alloc_destroy_n(noinit_adaptor<A> &,T * p,std::size_t n)40 alloc_destroy_n(noinit_adaptor<A>&, T* p, std::size_t n)
41 {
42 while (n > 0) {
43 p[--n].~T();
44 }
45 }
46
47 namespace detail {
48
49 template<class A, class T>
50 class alloc_destroyer {
51 public:
alloc_destroyer(A & a,T * p)52 alloc_destroyer(A& a, T* p) BOOST_NOEXCEPT
53 : a_(a),
54 p_(p),
55 n_(0) { }
56
~alloc_destroyer()57 ~alloc_destroyer() {
58 boost::alloc_destroy_n(a_, p_, n_);
59 }
60
size()61 std::size_t& size() BOOST_NOEXCEPT {
62 return n_;
63 }
64
65 private:
66 alloc_destroyer(const alloc_destroyer&);
67 alloc_destroyer& operator=(const alloc_destroyer&);
68
69 A& a_;
70 T* p_;
71 std::size_t n_;
72 };
73
74 } /* detail */
75
76 template<class A, class T>
77 inline void
alloc_construct(A & a,T * p)78 alloc_construct(A& a, T* p)
79 {
80 boost::allocator_construct(a, p);
81 }
82
83 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
84 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
85 template<class A, class T, class U, class... V>
86 inline void
alloc_construct(A & a,T * p,U && u,V &&...v)87 alloc_construct(A& a, T* p, U&& u, V&&... v)
88 {
89 boost::allocator_construct(a, p, std::forward<U>(u),
90 std::forward<V>(v)...);
91 }
92 #else
93 template<class A, class T, class U>
94 inline void
alloc_construct(A & a,T * p,U && u)95 alloc_construct(A& a, T* p, U&& u)
96 {
97 boost::allocator_construct(a, p, std::forward<U>(u));
98 }
99 #endif
100 #else
101 template<class A, class T, class U>
102 inline void
alloc_construct(A & a,T * p,const U & u)103 alloc_construct(A& a, T* p, const U& u)
104 {
105 boost::allocator_construct(a, p, u);
106 }
107
108 template<class A, class T, class U>
109 inline void
alloc_construct(A & a,T * p,U & u)110 alloc_construct(A& a, T* p, U& u)
111 {
112 boost::allocator_construct(a, p, u);
113 }
114 #endif
115
116 template<class A, class T>
117 inline void
alloc_construct_n(A & a,T * p,std::size_t n)118 alloc_construct_n(A& a, T* p, std::size_t n)
119 {
120 detail::alloc_destroyer<A, T> hold(a, p);
121 for (std::size_t& i = hold.size(); i < n; ++i) {
122 boost::allocator_construct(a, p + i);
123 }
124 hold.size() = 0;
125 }
126
127 template<class A, class T>
128 inline void
alloc_construct_n(A & a,T * p,std::size_t n,const T * l,std::size_t m)129 alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m)
130 {
131 detail::alloc_destroyer<A, T> hold(a, p);
132 for (std::size_t& i = hold.size(); i < n; ++i) {
133 boost::allocator_construct(a, p + i, l[i % m]);
134 }
135 hold.size() = 0;
136 }
137
138 template<class A, class T, class I>
139 inline void
alloc_construct_n(A & a,T * p,std::size_t n,I b)140 alloc_construct_n(A& a, T* p, std::size_t n, I b)
141 {
142 detail::alloc_destroyer<A, T> hold(a, p);
143 for (std::size_t& i = hold.size(); i < n; void(++i), void(++b)) {
144 boost::allocator_construct(a, p + i, *b);
145 }
146 hold.size() = 0;
147 }
148
149 template<class A, class T>
150 inline void
alloc_construct(noinit_adaptor<A> &,T * p)151 alloc_construct(noinit_adaptor<A>&, T* p)
152 {
153 ::new(static_cast<void*>(p)) T;
154 }
155
156 template<class A, class T>
157 inline void
alloc_construct_n(noinit_adaptor<A> & a,T * p,std::size_t n)158 alloc_construct_n(noinit_adaptor<A>& a, T* p, std::size_t n)
159 {
160 detail::alloc_destroyer<noinit_adaptor<A>, T> hold(a, p);
161 for (std::size_t& i = hold.size(); i < n; ++i) {
162 ::new(static_cast<void*>(p + i)) T;
163 }
164 hold.size() = 0;
165 }
166
167 } /* boost */
168
169 #endif
170