]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/smart_ptr/allocate_unique.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / smart_ptr / allocate_unique.hpp
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_SMART_PTR_ALLOCATE_UNIQUE_HPP
9 #define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
10
11 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
12 #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
13 #include <boost/core/alloc_construct.hpp>
14 #include <boost/core/empty_value.hpp>
15 #include <boost/core/first_scalar.hpp>
16 #include <boost/core/noinit_adaptor.hpp>
17 #include <boost/core/pointer_traits.hpp>
18 #include <boost/type_traits/enable_if.hpp>
19 #include <boost/type_traits/extent.hpp>
20 #include <boost/type_traits/is_array.hpp>
21 #include <boost/type_traits/is_bounded_array.hpp>
22 #include <boost/type_traits/is_unbounded_array.hpp>
23 #include <boost/type_traits/remove_cv.hpp>
24 #include <boost/type_traits/remove_extent.hpp>
25 #include <boost/type_traits/type_identity.hpp>
26 #include <boost/config.hpp>
27 #include <memory>
28 #include <utility>
29
30 namespace boost {
31 namespace detail {
32
33 template<class T>
34 struct sp_alloc_size {
35 BOOST_STATIC_CONSTEXPR std::size_t value = 1;
36 };
37
38 template<class T>
39 struct sp_alloc_size<T[]> {
40 BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;
41 };
42
43 template<class T, std::size_t N>
44 struct sp_alloc_size<T[N]> {
45 BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size<T>::value;
46 };
47
48 template<class T>
49 struct sp_alloc_result {
50 typedef T type;
51 };
52
53 template<class T, std::size_t N>
54 struct sp_alloc_result<T[N]> {
55 typedef T type[];
56 };
57
58 template<class T>
59 struct sp_alloc_value {
60 typedef typename boost::remove_cv<typename
61 boost::remove_extent<T>::type>::type type;
62 };
63
64 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
65 template<class A, class T>
66 struct sp_alloc_to {
67 typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
68 };
69 #else
70 template<class A, class T>
71 struct sp_alloc_to {
72 typedef typename A::template rebind<T>::other type;
73 };
74 #endif
75
76 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
77 template<class A>
78 struct sp_alloc_type {
79 typedef typename std::allocator_traits<A>::pointer type;
80 };
81 #else
82 template<class A>
83 struct sp_alloc_type {
84 typedef typename A::pointer type;
85 };
86 #endif
87
88 template<class T, class P>
89 class sp_alloc_ptr {
90 public:
91 typedef T element_type;
92
93 sp_alloc_ptr() BOOST_SP_NOEXCEPT
94 : p_() { }
95
96 #if defined(BOOST_MSVC) && BOOST_MSVC == 1600
97 sp_alloc_ptr(T* p) BOOST_SP_NOEXCEPT
98 : p_(const_cast<typename boost::remove_cv<T>::type*>(p)) { }
99 #endif
100
101 sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
102 : p_(p) { }
103
104 #if !defined(BOOST_NO_CXX11_NULLPTR)
105 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
106 : p_() { }
107 #endif
108
109 T& operator*() const {
110 return *p_;
111 }
112
113 T* operator->() const BOOST_SP_NOEXCEPT {
114 return boost::to_address(p_);
115 }
116
117 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
118 explicit operator bool() const BOOST_SP_NOEXCEPT {
119 return !!p_;
120 }
121 #endif
122
123 bool operator!() const BOOST_SP_NOEXCEPT {
124 return !p_;
125 }
126
127 P ptr() const BOOST_SP_NOEXCEPT {
128 return p_;
129 }
130
131 BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
132 return 1;
133 }
134
135 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
136 static sp_alloc_ptr pointer_to(T& v) {
137 return sp_alloc_ptr(1,
138 std::pointer_traits<P>::pointer_to(const_cast<typename
139 boost::remove_cv<T>::type&>(v)));
140 }
141 #endif
142
143 private:
144 P p_;
145 };
146
147 template<class T, class P>
148 class sp_alloc_ptr<T[], P> {
149 public:
150 typedef T element_type;
151
152 sp_alloc_ptr() BOOST_SP_NOEXCEPT
153 : p_() { }
154
155 sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT
156 : p_(p)
157 , n_(n) { }
158
159 #if !defined(BOOST_NO_CXX11_NULLPTR)
160 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
161 : p_() { }
162 #endif
163
164 T& operator[](std::size_t i) const {
165 return p_[i];
166 }
167
168 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
169 explicit operator bool() const BOOST_SP_NOEXCEPT {
170 return !!p_;
171 }
172 #endif
173
174 bool operator!() const BOOST_SP_NOEXCEPT {
175 return !p_;
176 }
177
178 P ptr() const BOOST_SP_NOEXCEPT {
179 return p_;
180 }
181
182 std::size_t size() const BOOST_SP_NOEXCEPT {
183 return n_;
184 }
185
186 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
187 static sp_alloc_ptr pointer_to(T& v) {
188 return sp_alloc_ptr(n_,
189 std::pointer_traits<P>::pointer_to(const_cast<typename
190 boost::remove_cv<T>::type&>(v)));
191 }
192 #endif
193
194 private:
195 P p_;
196 std::size_t n_;
197 };
198
199 template<class T, std::size_t N, class P>
200 class sp_alloc_ptr<T[N], P> {
201 public:
202 typedef T element_type;
203
204 sp_alloc_ptr() BOOST_SP_NOEXCEPT
205 : p_() { }
206
207 sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
208 : p_(p) { }
209
210 #if !defined(BOOST_NO_CXX11_NULLPTR)
211 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
212 : p_() { }
213 #endif
214
215 T& operator[](std::size_t i) const {
216 return p_[i];
217 }
218
219 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
220 explicit operator bool() const BOOST_SP_NOEXCEPT {
221 return !!p_;
222 }
223 #endif
224
225 bool operator!() const BOOST_SP_NOEXCEPT {
226 return !p_;
227 }
228
229 P ptr() const BOOST_SP_NOEXCEPT {
230 return p_;
231 }
232
233 BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
234 return N;
235 }
236
237 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
238 static sp_alloc_ptr pointer_to(T& v) {
239 return sp_alloc_ptr(N,
240 std::pointer_traits<P>::pointer_to(const_cast<typename
241 boost::remove_cv<T>::type&>(v)));
242 }
243 #endif
244
245 private:
246 P p_;
247 };
248
249 template<class T, class P>
250 inline bool
251 operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
252 {
253 return lhs.ptr() == rhs.ptr();
254 }
255
256 template<class T, class P>
257 inline bool
258 operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
259 {
260 return !(lhs == rhs);
261 }
262
263 #if !defined(BOOST_NO_CXX11_NULLPTR)
264 template<class T, class P>
265 inline bool
266 operator==(const sp_alloc_ptr<T, P>& lhs,
267 detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
268 {
269 return !lhs.ptr();
270 }
271
272 template<class T, class P>
273 inline bool
274 operator==(detail::sp_nullptr_t,
275 const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
276 {
277 return !rhs.ptr();
278 }
279
280 template<class T, class P>
281 inline bool
282 operator!=(const sp_alloc_ptr<T, P>& lhs,
283 detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
284 {
285 return !!lhs.ptr();
286 }
287
288 template<class T, class P>
289 inline bool
290 operator!=(detail::sp_nullptr_t,
291 const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
292 {
293 return !!rhs.ptr();
294 }
295 #endif
296
297 template<class A>
298 inline void
299 sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,
300 boost::false_type)
301 {
302 boost::alloc_destroy(a, boost::to_address(p));
303 }
304
305 template<class A>
306 inline void
307 sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,
308 boost::true_type)
309 {
310 #if defined(BOOST_MSVC) && BOOST_MSVC < 1800
311 if (!p) {
312 return;
313 }
314 #endif
315 boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
316 n * sp_alloc_size<typename A::value_type>::value);
317 }
318
319 } /* detail */
320
321 template<class T, class A>
322 class alloc_deleter
323 : empty_value<typename detail::sp_alloc_to<A,
324 typename detail::sp_alloc_value<T>::type>::type> {
325 typedef typename detail::sp_alloc_to<A,
326 typename detail::sp_alloc_value<T>::type>::type allocator;
327 typedef empty_value<allocator> base;
328
329 public:
330 typedef detail::sp_alloc_ptr<T,
331 typename detail::sp_alloc_type<allocator>::type> pointer;
332
333 explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT
334 : base(empty_init_t(), a) { }
335
336 void operator()(pointer p) {
337 detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), is_array<T>());
338 base::get().deallocate(p.ptr(), p.size());
339 }
340 };
341
342 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
343 template<class T, class A>
344 using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;
345 #endif
346
347 namespace detail {
348
349 template<class T, class A>
350 class sp_alloc_make {
351 public:
352 typedef typename sp_alloc_to<A,
353 typename sp_alloc_value<T>::type>::type allocator;
354
355 private:
356 typedef boost::alloc_deleter<T, A> deleter;
357
358 public:
359 typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
360
361 sp_alloc_make(const A& a, std::size_t n)
362 : a_(a)
363 , n_(n)
364 , p_(a_.allocate(n)) { }
365
366 ~sp_alloc_make() {
367 if (p_) {
368 a_.deallocate(p_, n_);
369 }
370 }
371
372 typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {
373 return boost::to_address(p_);
374 }
375
376 allocator& state() BOOST_SP_NOEXCEPT {
377 return a_;
378 }
379
380 type release() BOOST_SP_NOEXCEPT {
381 pointer p = p_;
382 p_ = pointer();
383 return type(typename deleter::pointer(n_, p), deleter(a_));
384 }
385
386 private:
387 typedef typename sp_alloc_type<allocator>::type pointer;
388
389 allocator a_;
390 std::size_t n_;
391 pointer p_;
392 };
393
394 } /* detail */
395
396 template<class T, class A>
397 inline typename enable_if_<!is_array<T>::value,
398 std::unique_ptr<T, alloc_deleter<T, A> > >::type
399 allocate_unique(const A& alloc)
400 {
401 detail::sp_alloc_make<T, A> c(alloc, 1);
402 boost::alloc_construct(c.state(), c.get());
403 return c.release();
404 }
405
406 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
407 template<class T, class A, class... Args>
408 inline typename enable_if_<!is_array<T>::value,
409 std::unique_ptr<T, alloc_deleter<T, A> > >::type
410 allocate_unique(const A& alloc, Args&&... args)
411 {
412 detail::sp_alloc_make<T, A> c(alloc, 1);
413 boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
414 return c.release();
415 }
416 #endif
417
418 template<class T, class A>
419 inline typename enable_if_<!is_array<T>::value,
420 std::unique_ptr<T, alloc_deleter<T, A> > >::type
421 allocate_unique(const A& alloc, typename type_identity<T>::type&& value)
422 {
423 detail::sp_alloc_make<T, A> c(alloc, 1);
424 boost::alloc_construct(c.state(), c.get(), std::move(value));
425 return c.release();
426 }
427
428 template<class T, class A>
429 inline typename enable_if_<!is_array<T>::value,
430 std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
431 allocate_unique_noinit(const A& alloc)
432 {
433 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
434 }
435
436 template<class T, class A>
437 inline typename enable_if_<is_unbounded_array<T>::value,
438 std::unique_ptr<T, alloc_deleter<T, A> > >::type
439 allocate_unique(const A& alloc, std::size_t size)
440 {
441 detail::sp_alloc_make<T, A> c(alloc, size);
442 boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
443 size * detail::sp_alloc_size<T>::value);
444 return c.release();
445 }
446
447 template<class T, class A>
448 inline typename enable_if_<is_bounded_array<T>::value,
449 std::unique_ptr<typename detail::sp_alloc_result<T>::type,
450 alloc_deleter<T, A> > >::type
451 allocate_unique(const A& alloc)
452 {
453 detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
454 boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
455 detail::sp_alloc_size<T>::value);
456 return c.release();
457 }
458
459 template<class T, class A>
460 inline typename enable_if_<is_unbounded_array<T>::value,
461 std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
462 allocate_unique_noinit(const A& alloc, std::size_t size)
463 {
464 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
465 }
466
467 template<class T, class A>
468 inline typename enable_if_<is_bounded_array<T>::value,
469 std::unique_ptr<typename detail::sp_alloc_result<T>::type,
470 alloc_deleter<T, noinit_adaptor<A> > > >::type
471 allocate_unique_noinit(const A& alloc)
472 {
473 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
474 }
475
476 template<class T, class A>
477 inline typename enable_if_<is_unbounded_array<T>::value,
478 std::unique_ptr<T, alloc_deleter<T, A> > >::type
479 allocate_unique(const A& alloc, std::size_t size,
480 const typename remove_extent<T>::type& value)
481 {
482 detail::sp_alloc_make<T, A> c(alloc, size);
483 boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
484 size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
485 detail::sp_alloc_size<typename remove_extent<T>::type>::value);
486 return c.release();
487 }
488
489 template<class T, class A>
490 inline typename enable_if_<is_bounded_array<T>::value,
491 std::unique_ptr<typename detail::sp_alloc_result<T>::type,
492 alloc_deleter<T, A> > >::type
493 allocate_unique(const A& alloc,
494 const typename remove_extent<T>::type& value)
495 {
496 detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
497 boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
498 detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
499 detail::sp_alloc_size<typename remove_extent<T>::type>::value);
500 return c.release();
501 }
502
503 } /* boost */
504
505 #endif