2 Copyright 2019 Glen Joseph Fernandes
5 Distributed under the Boost Software License, Version 1.0.
6 (http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
9 #define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
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>
34 struct sp_alloc_size {
35 BOOST_STATIC_CONSTEXPR std::size_t value = 1;
39 struct sp_alloc_size<T[]> {
40 BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;
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;
49 struct sp_alloc_result {
53 template<class T, std::size_t N>
54 struct sp_alloc_result<T[N]> {
59 struct sp_alloc_value {
60 typedef typename boost::remove_cv<typename
61 boost::remove_extent<T>::type>::type type;
64 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
65 template<class A, class T>
67 typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
70 template<class A, class T>
72 typedef typename A::template rebind<T>::other type;
76 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
78 struct sp_alloc_type {
79 typedef typename std::allocator_traits<A>::pointer type;
83 struct sp_alloc_type {
84 typedef typename A::pointer type;
88 template<class T, class P>
91 typedef T element_type;
93 sp_alloc_ptr() BOOST_SP_NOEXCEPT
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)) { }
101 sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
104 #if !defined(BOOST_NO_CXX11_NULLPTR)
105 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
109 T& operator*() const {
113 T* operator->() const BOOST_SP_NOEXCEPT {
114 return boost::to_address(p_);
117 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
118 explicit operator bool() const BOOST_SP_NOEXCEPT {
123 bool operator!() const BOOST_SP_NOEXCEPT {
127 P ptr() const BOOST_SP_NOEXCEPT {
131 BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
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)));
147 template<class T, class P>
148 class sp_alloc_ptr<T[], P> {
150 typedef T element_type;
152 sp_alloc_ptr() BOOST_SP_NOEXCEPT
155 sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT
159 #if !defined(BOOST_NO_CXX11_NULLPTR)
160 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
164 T& operator[](std::size_t i) const {
168 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
169 explicit operator bool() const BOOST_SP_NOEXCEPT {
174 bool operator!() const BOOST_SP_NOEXCEPT {
178 P ptr() const BOOST_SP_NOEXCEPT {
182 std::size_t size() const BOOST_SP_NOEXCEPT {
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)));
199 template<class T, std::size_t N, class P>
200 class sp_alloc_ptr<T[N], P> {
202 typedef T element_type;
204 sp_alloc_ptr() BOOST_SP_NOEXCEPT
207 sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
210 #if !defined(BOOST_NO_CXX11_NULLPTR)
211 sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
215 T& operator[](std::size_t i) const {
219 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
220 explicit operator bool() const BOOST_SP_NOEXCEPT {
225 bool operator!() const BOOST_SP_NOEXCEPT {
229 P ptr() const BOOST_SP_NOEXCEPT {
233 BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
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)));
249 template<class T, class P>
251 operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
253 return lhs.ptr() == rhs.ptr();
256 template<class T, class P>
258 operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
260 return !(lhs == rhs);
263 #if !defined(BOOST_NO_CXX11_NULLPTR)
264 template<class T, class P>
266 operator==(const sp_alloc_ptr<T, P>& lhs,
267 detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
272 template<class T, class P>
274 operator==(detail::sp_nullptr_t,
275 const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
280 template<class T, class P>
282 operator!=(const sp_alloc_ptr<T, P>& lhs,
283 detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
288 template<class T, class P>
290 operator!=(detail::sp_nullptr_t,
291 const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
299 sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,
302 boost::alloc_destroy(a, boost::to_address(p));
307 sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,
310 #if defined(BOOST_MSVC) && BOOST_MSVC < 1800
315 boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
316 n * sp_alloc_size<typename A::value_type>::value);
321 template<class T, class A>
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;
330 typedef detail::sp_alloc_ptr<T,
331 typename detail::sp_alloc_type<allocator>::type> pointer;
333 explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT
334 : base(empty_init_t(), a) { }
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());
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> >;
349 template<class T, class A>
350 class sp_alloc_make {
352 typedef typename sp_alloc_to<A,
353 typename sp_alloc_value<T>::type>::type allocator;
356 typedef boost::alloc_deleter<T, A> deleter;
359 typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
361 sp_alloc_make(const A& a, std::size_t n)
364 , p_(a_.allocate(n)) { }
368 a_.deallocate(p_, n_);
372 typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {
373 return boost::to_address(p_);
376 allocator& state() BOOST_SP_NOEXCEPT {
380 type release() BOOST_SP_NOEXCEPT {
383 return type(typename deleter::pointer(n_, p), deleter(a_));
387 typedef typename sp_alloc_type<allocator>::type pointer;
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)
401 detail::sp_alloc_make<T, A> c(alloc, 1);
402 boost::alloc_construct(c.state(), c.get());
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)
412 detail::sp_alloc_make<T, A> c(alloc, 1);
413 boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
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)
423 detail::sp_alloc_make<T, A> c(alloc, 1);
424 boost::alloc_construct(c.state(), c.get(), std::move(value));
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)
433 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
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)
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);
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)
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);
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)
464 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
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)
473 return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
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)
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);
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)
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);