Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / smart_ptr / allocate_shared_array.hpp
1 /*
2 Copyright 2012-2017 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_SHARED_ARRAY_HPP
9 #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
10
11 #include <boost/smart_ptr/shared_ptr.hpp>
12 #include <boost/type_traits/has_trivial_constructor.hpp>
13 #include <boost/type_traits/has_trivial_destructor.hpp>
14 #include <boost/type_traits/alignment_of.hpp>
15 #include <boost/type_traits/type_with_alignment.hpp>
16
17 namespace boost {
18 namespace detail {
19
20 template<class>
21 struct sp_if_array { };
22
23 template<class T>
24 struct sp_if_array<T[]> {
25     typedef boost::shared_ptr<T[]> type;
26 };
27
28 template<class>
29 struct sp_if_size_array { };
30
31 template<class T, std::size_t N>
32 struct sp_if_size_array<T[N]> {
33     typedef boost::shared_ptr<T[N]> type;
34 };
35
36 template<class>
37 struct sp_array_element { };
38
39 template<class T>
40 struct sp_array_element<T[]> {
41     typedef T type;
42 };
43
44 template<class T, std::size_t N>
45 struct sp_array_element<T[N]> {
46     typedef T type;
47 };
48
49 template<class T>
50 struct sp_array_scalar {
51     typedef T type;
52 };
53
54 template<class T, std::size_t N>
55 struct sp_array_scalar<T[N]> {
56     typedef typename sp_array_scalar<T>::type type;
57 };
58
59 template<class T, std::size_t N>
60 struct sp_array_scalar<const T[N]> {
61     typedef typename sp_array_scalar<T>::type type;
62 };
63
64 template<class T, std::size_t N>
65 struct sp_array_scalar<volatile T[N]> {
66     typedef typename sp_array_scalar<T>::type type;
67 };
68
69 template<class T, std::size_t N>
70 struct sp_array_scalar<const volatile T[N]> {
71     typedef typename sp_array_scalar<T>::type type;
72 };
73
74 template<class T>
75 struct sp_array_scalar<T[]> {
76     typedef typename sp_array_scalar<T>::type type;
77 };
78
79 template<class T>
80 struct sp_array_scalar<const T[]> {
81     typedef typename sp_array_scalar<T>::type type;
82 };
83
84 template<class T>
85 struct sp_array_scalar<volatile T[]> {
86     typedef typename sp_array_scalar<T>::type type;
87 };
88
89 template<class T>
90 struct sp_array_scalar<const volatile T[]> {
91     typedef typename sp_array_scalar<T>::type type;
92 };
93
94 template<class T>
95 struct sp_array_count {
96     enum {
97         value = 1
98     };
99 };
100
101 template<class T, std::size_t N>
102 struct sp_array_count<T[N]> {
103     enum {
104         value = N * sp_array_count<T>::value
105     };
106 };
107
108 template<class T>
109 struct sp_array_count<T[]> { };
110
111 template<class D, class T>
112 inline D*
113 sp_get_deleter(const
114     boost::shared_ptr<T>& value) BOOST_NOEXCEPT_OR_NOTHROW
115 {
116     return static_cast<D*>(value._internal_get_untyped_deleter());
117 }
118
119 template<std::size_t N, std::size_t A>
120 struct sp_array_storage {
121     union type {
122         char value[N];
123         typename boost::type_with_alignment<A>::type other;
124     };
125 };
126
127 template<std::size_t N, std::size_t M>
128 struct sp_max_size {
129     enum {
130         value = N < M ? M : N
131     };
132 };
133
134 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
135 template<class A, class T>
136 struct sp_bind_allocator {
137     typedef typename std::allocator_traits<A>::template
138         rebind_alloc<T> type;
139 };
140 #else
141 template<class A, class T>
142 struct sp_bind_allocator {
143     typedef typename A::template rebind<T>::other type;
144 };
145 #endif
146
147 template<bool, class = void>
148 struct sp_enable { };
149
150 template<class T>
151 struct sp_enable<true, T> {
152     typedef T type;
153 };
154
155 template<class T>
156 inline
157 typename sp_enable<boost::has_trivial_destructor<T>::value>::type
158 sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { }
159
160 template<class T>
161 inline
162 typename sp_enable<!boost::has_trivial_destructor<T>::value>::type
163 sp_array_destroy(T* storage, std::size_t size)
164 {
165     while (size > 0) {
166         storage[--size].~T();
167     }
168 }
169
170 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
171 template<class A, class T>
172 inline void
173 sp_array_destroy(A& allocator, T* storage, std::size_t size)
174 {
175     while (size > 0) {
176         std::allocator_traits<A>::destroy(allocator, &storage[--size]);
177     }
178 }
179 #endif
180
181 #if !defined(BOOST_NO_EXCEPTIONS)
182 template<class T>
183 inline
184 typename sp_enable<boost::has_trivial_constructor<T>::value ||
185     boost::has_trivial_destructor<T>::value>::type
186 sp_array_construct(T* storage, std::size_t size)
187 {
188     for (std::size_t i = 0; i < size; ++i) {
189         ::new(static_cast<void*>(storage + i)) T();
190     }
191 }
192
193 template<class T>
194 inline
195 typename sp_enable<!boost::has_trivial_constructor<T>::value &&
196     !boost::has_trivial_destructor<T>::value>::type
197 sp_array_construct(T* storage, std::size_t size)
198 {
199     std::size_t i = 0;
200     try {
201         for (; i < size; ++i) {
202             ::new(static_cast<void*>(storage + i)) T();
203         }
204     } catch (...) {
205         while (i > 0) {
206             storage[--i].~T();
207         }
208         throw;
209     }
210 }
211
212 template<class T>
213 inline void
214 sp_array_construct(T* storage, std::size_t size, const T* list,
215     std::size_t count)
216 {
217     std::size_t i = 0;
218     try {
219         for (; i < size; ++i) {
220             ::new(static_cast<void*>(storage + i)) T(list[i % count]);
221         }
222     } catch (...) {
223         while (i > 0) {
224             storage[--i].~T();
225         }
226         throw;
227     }
228 }
229 #else
230 template<class T>
231 inline void
232 sp_array_construct(T* storage, std::size_t size)
233 {
234     for (std::size_t i = 0; i < size; ++i) {
235         ::new(static_cast<void*>(storage + i)) T();
236     }
237 }
238
239 template<class T>
240 inline void
241 sp_array_construct(T* storage, std::size_t size, const T* list,
242     std::size_t count)
243 {
244     for (std::size_t i = 0; i < size; ++i) {
245         ::new(static_cast<void*>(storage + i)) T(list[i % count]);
246     }
247 }
248 #endif
249
250 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
251 #if !defined(BOOST_NO_EXCEPTIONS)
252 template<class A, class T>
253 inline void
254 sp_array_construct(A& allocator, T* storage, std::size_t size)
255 {
256     std::size_t i = 0;
257     try {
258         for (i = 0; i < size; ++i) {
259             std::allocator_traits<A>::construct(allocator, storage + i);
260         }
261     } catch (...) {
262         sp_array_destroy(allocator, storage, i);
263         throw;
264     }
265 }
266
267 template<class A, class T>
268 inline void
269 sp_array_construct(A& allocator, T* storage, std::size_t size,
270     const T* list, std::size_t count)
271 {
272     std::size_t i = 0;
273     try {
274         for (i = 0; i < size; ++i) {
275             std::allocator_traits<A>::construct(allocator, storage + i,
276                 list[i % count]);
277         }
278     } catch (...) {
279         sp_array_destroy(allocator, storage, i);
280         throw;
281     }
282 }
283 #else
284 template<class A, class T>
285 inline void
286 sp_array_construct(A& allocator, T* storage, std::size_t size)
287 {
288     for (std::size_t i = 0; i < size; ++i) {
289         std::allocator_traits<A>::construct(allocator, storage + i);
290     }
291 }
292
293 template<class A, class T>
294 inline void
295 sp_array_construct(A& allocator, T* storage, std::size_t size,
296     const T* list, std::size_t count)
297 {
298     for (std::size_t i = 0; i < size; ++i) {
299         std::allocator_traits<A>::construct(allocator, storage + i,
300             list[i % count]);
301     }
302 }
303 #endif
304 #endif
305
306 template<class T>
307 inline
308 typename sp_enable<boost::has_trivial_constructor<T>::value>::type
309 sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { }
310
311 #if !defined(BOOST_NO_EXCEPTIONS)
312 template<class T>
313 inline
314 typename sp_enable<!boost::has_trivial_constructor<T>::value &&
315     boost::has_trivial_destructor<T>::value>::type
316 sp_array_default(T* storage, std::size_t size)
317 {
318     for (std::size_t i = 0; i < size; ++i) {
319         ::new(static_cast<void*>(storage + i)) T;
320     }
321 }
322
323 template<class T>
324 inline
325 typename sp_enable<!boost::has_trivial_constructor<T>::value &&
326     !boost::has_trivial_destructor<T>::value>::type
327 sp_array_default(T* storage, std::size_t size)
328 {
329     std::size_t i = 0;
330     try {
331         for (; i < size; ++i) {
332             ::new(static_cast<void*>(storage + i)) T;
333         }
334     } catch (...) {
335         while (i > 0) {
336             storage[--i].~T();
337         }
338         throw;
339     }
340 }
341 #else
342 template<class T>
343 inline
344 typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
345 sp_array_default(T* storage, std::size_t size)
346 {
347     for (std::size_t i = 0; i < size; ++i) {
348         ::new(static_cast<void*>(storage + i)) T;
349     }
350 }
351 #endif
352
353 template<class T, std::size_t N>
354 struct sp_less_align {
355     enum {
356         value = (boost::alignment_of<T>::value) < N
357     };
358 };
359
360 template<class T, std::size_t N>
361 BOOST_CONSTEXPR inline
362 typename sp_enable<sp_less_align<T, N>::value, std::size_t>::type
363 sp_align(std::size_t size) BOOST_NOEXCEPT
364 {
365     return (sizeof(T) * size + N - 1) & ~(N - 1);
366 }
367
368 template<class T, std::size_t N>
369 BOOST_CONSTEXPR inline
370 typename sp_enable<!sp_less_align<T, N>::value, std::size_t>::type
371 sp_align(std::size_t size) BOOST_NOEXCEPT
372 {
373     return sizeof(T) * size;
374 }
375
376 template<class T>
377 BOOST_CONSTEXPR inline std::size_t
378 sp_types(std::size_t size) BOOST_NOEXCEPT
379 {
380     return (size + sizeof(T) - 1) / sizeof(T);
381 }
382
383 template<class T, std::size_t N>
384 class sp_size_array_deleter {
385 public:
386     template<class U>
387     static void operator_fn(U) BOOST_NOEXCEPT { }
388
389     sp_size_array_deleter() BOOST_NOEXCEPT
390         : enabled_(false) { }
391
392     template<class A>
393     sp_size_array_deleter(const A&) BOOST_NOEXCEPT
394         : enabled_(false) { }
395
396     sp_size_array_deleter(const sp_size_array_deleter&) BOOST_NOEXCEPT
397         : enabled_(false) { }
398
399     ~sp_size_array_deleter() {
400         if (enabled_) {
401             sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
402         }
403     }
404
405     template<class U>
406     void operator()(U) {
407         if (enabled_) {
408             sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
409             enabled_ = false;
410         }
411     }
412
413     void* construct() {
414         sp_array_construct(reinterpret_cast<T*>(&storage_), N);
415         enabled_ = true;
416         return &storage_;
417     }
418
419     void* construct(const T* list, std::size_t count) {
420         sp_array_construct(reinterpret_cast<T*>(&storage_), N,
421             list, count);
422         enabled_ = true;
423         return &storage_;
424     }
425
426     void* construct_default() {
427         sp_array_default(reinterpret_cast<T*>(&storage_), N);
428         enabled_ = true;
429         return &storage_;
430     }
431
432 private:
433     bool enabled_;
434     typename sp_array_storage<sizeof(T) * N,
435         boost::alignment_of<T>::value>::type storage_;
436 };
437
438 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
439 template<class T, std::size_t N, class A>
440 class sp_size_array_destroyer {
441 public:
442     template<class U>
443     static void operator_fn(U) BOOST_NOEXCEPT { }
444
445     template<class U>
446     sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT
447         : allocator_(allocator),
448           enabled_(false) { }
449
450     sp_size_array_destroyer(const sp_size_array_destroyer& other)
451         BOOST_NOEXCEPT
452         : allocator_(other.allocator_),
453           enabled_(false) { }
454
455     ~sp_size_array_destroyer() {
456         if (enabled_) {
457             sp_array_destroy(allocator_,
458                 reinterpret_cast<T*>(&storage_), N);
459         }
460     }
461
462     template<class U>
463     void operator()(U) {
464         if (enabled_) {
465             sp_array_destroy(allocator_,
466                 reinterpret_cast<T*>(&storage_), N);
467             enabled_ = false;
468         }
469     }
470
471     void* construct() {
472         sp_array_construct(allocator_,
473             reinterpret_cast<T*>(&storage_), N);
474         enabled_ = true;
475         return &storage_;
476     }
477
478     void* construct(const T* list, std::size_t count) {
479         sp_array_construct(allocator_,
480             reinterpret_cast<T*>(&storage_), N, list, count);
481         enabled_ = true;
482         return &storage_;
483     }
484
485     const A& allocator() const BOOST_NOEXCEPT {
486         return allocator_;
487     }
488
489 private:
490     typename sp_array_storage<sizeof(T) * N,
491         boost::alignment_of<T>::value>::type storage_;
492     A allocator_;
493     bool enabled_;
494 };
495 #endif
496
497 template<class T>
498 class sp_array_deleter {
499 public:
500     template<class U>
501     static void operator_fn(U) BOOST_NOEXCEPT { }
502
503     sp_array_deleter(std::size_t size) BOOST_NOEXCEPT
504         : address_(0),
505           size_(size) { }
506
507     template<class A>
508     sp_array_deleter(const A& allocator) BOOST_NOEXCEPT
509         : address_(0),
510           size_(allocator.size()) { }
511
512     template<class A>
513     sp_array_deleter(const A&, std::size_t size) BOOST_NOEXCEPT
514         : address_(0),
515           size_(size) { }
516
517     sp_array_deleter(const sp_array_deleter& other) BOOST_NOEXCEPT
518         : address_(0),
519           size_(other.size_) { }
520
521     ~sp_array_deleter() {
522         if (address_) {
523             sp_array_destroy(static_cast<T*>(address_), size_);
524         }
525     }
526
527     template<class U>
528     void operator()(U) {
529         if (address_) {
530             sp_array_destroy(static_cast<T*>(address_), size_);
531             address_ = 0;
532         }
533     }
534
535     void construct(T* address) {
536         sp_array_construct(address, size_);
537         address_ = address;
538     }
539
540     void construct(T* address, const T* list, std::size_t count) {
541         sp_array_construct(address, size_, list, count);
542         address_ = address;
543     }
544
545     void construct_default(T* address) {
546         sp_array_default(address, size_);
547         address_ = address;
548     }
549
550     std::size_t size() const BOOST_NOEXCEPT {
551         return size_;
552     }
553
554 private:
555     void* address_;
556     std::size_t size_;
557 };
558
559 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
560 template<class T, class A>
561 class sp_array_destroyer {
562 public:
563     template<class U>
564     static void operator_fn(U) BOOST_NOEXCEPT { }
565
566     template<class U>
567     sp_array_destroyer(const U& allocator, std::size_t size)
568         BOOST_NOEXCEPT
569         : allocator_(allocator),
570           size_(size),
571           address_(0) { }
572
573     template<class U>
574     sp_array_destroyer(const U& allocator) BOOST_NOEXCEPT
575         : allocator_(allocator.allocator()),
576           size_(allocator.size()),
577           address_(0) { }
578
579     sp_array_destroyer(const sp_array_destroyer& other) BOOST_NOEXCEPT
580         : allocator_(other.allocator_),
581           size_(other.size_),
582           address_(0) { }
583
584     ~sp_array_destroyer() {
585         if (address_) {
586             sp_array_destroy(allocator_, static_cast<T*>(address_),
587                 size_);
588         }
589     }
590
591     template<class U>
592     void operator()(U) {
593         if (address_) {
594             sp_array_destroy(allocator_, static_cast<T*>(address_),
595                 size_);
596             address_ = 0;
597         }
598     }
599
600     void construct(T* address) {
601         sp_array_construct(allocator_, address, size_);
602         address_ = address;
603     }
604
605     void construct(T* address, const T* list, std::size_t count) {
606         sp_array_construct(allocator_, address, size_, list, count);
607         address_ = address;
608     }
609
610     const A& allocator() const BOOST_NOEXCEPT {
611         return allocator_;
612     }
613
614     std::size_t size() const BOOST_NOEXCEPT {
615         return size_;
616     }
617
618 private:
619     A allocator_;
620     std::size_t size_;
621     void* address_;
622 };
623 #endif
624
625 template<class T, class A>
626 class sp_array_allocator {
627     template<class U, class V>
628     friend class sp_array_allocator;
629
630 public:
631     typedef typename A::value_type value_type;
632
633 private:
634     enum {
635         alignment = sp_max_size<boost::alignment_of<T>::value,
636             boost::alignment_of<value_type>::value>::value
637     };
638
639     typedef typename boost::type_with_alignment<alignment>::type type;
640     typedef typename sp_bind_allocator<A, type>::type type_allocator;
641
642 public:
643     template<class U>
644     struct rebind {
645         typedef sp_array_allocator<T,
646             typename sp_bind_allocator<A, U>::type> other;
647     };
648
649     sp_array_allocator(const A& allocator, std::size_t size,
650         void** result) BOOST_NOEXCEPT
651         : allocator_(allocator),
652           size_(size),
653           result_(result) { }
654
655     sp_array_allocator(const A& allocator, std::size_t size)
656         BOOST_NOEXCEPT
657         : allocator_(allocator),
658           size_(size) { }
659
660     template<class U>
661     sp_array_allocator(const sp_array_allocator<T, U>& other)
662         BOOST_NOEXCEPT
663         : allocator_(other.allocator_),
664           size_(other.size_),
665           result_(other.result_) { }
666
667     value_type* allocate(std::size_t count) {
668         type_allocator allocator(allocator_);
669         std::size_t node = sp_align<value_type, alignment>(count);
670         std::size_t size = sp_types<type>(node + sizeof(T) * size_);
671         type* address = allocator.allocate(size);
672         *result_ = reinterpret_cast<char*>(address) + node;
673         return reinterpret_cast<value_type*>(address);
674     }
675
676     void deallocate(value_type* value, std::size_t count) {
677         type_allocator allocator(allocator_);
678         std::size_t node = sp_align<value_type, alignment>(count);
679         std::size_t size = sp_types<type>(node + sizeof(T) * size_);
680         allocator.deallocate(reinterpret_cast<type*>(value), size);
681     }
682
683     const A& allocator() const BOOST_NOEXCEPT {
684         return allocator_;
685     }
686
687     std::size_t size() const BOOST_NOEXCEPT {
688         return size_;
689     }
690
691 private:
692     A allocator_;
693     std::size_t size_;
694     void** result_;
695 };
696
697 template<class T, class U, class V>
698 inline bool
699 operator==(const sp_array_allocator<T, U>& first,
700     const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
701 {
702     return first.allocator() == second.allocator() &&
703         first.size() == second.size();
704 }
705
706 template<class T, class U, class V>
707 inline bool
708 operator!=(const sp_array_allocator<T, U>& first,
709     const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
710 {
711     return !(first == second);
712 }
713
714 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
715 template<class A, class T, std::size_t N>
716 struct sp_select_size_deleter {
717     typedef sp_size_array_destroyer<T, N,
718         typename sp_bind_allocator<A, T>::type> type;
719 };
720
721 template<class U, class T, std::size_t N>
722 struct sp_select_size_deleter<std::allocator<U>, T, N> {
723     typedef sp_size_array_deleter<T, N> type;
724 };
725
726 template<class A, class T>
727 struct sp_select_deleter {
728     typedef sp_array_destroyer<T,
729         typename sp_bind_allocator<A, T>::type> type;
730 };
731
732 template<class U, class T>
733 struct sp_select_deleter<std::allocator<U>, T> {
734     typedef sp_array_deleter<T> type;
735 };
736 #else
737 template<class, class T, std::size_t N>
738 struct sp_select_size_deleter {
739     typedef sp_size_array_deleter<T, N> type;
740 };
741
742 template<class, class T>
743 struct sp_select_deleter {
744     typedef sp_array_deleter<T> type;
745 };
746 #endif
747
748 template<class P, class T, std::size_t N, class A>
749 class sp_counted_impl_pda<P, sp_size_array_deleter<T, N>, A>
750     : public sp_counted_base {
751 public:
752     typedef sp_size_array_deleter<T, N> deleter_type;
753
754 private:
755     typedef sp_counted_impl_pda<P, deleter_type, A> type;
756     typedef typename sp_bind_allocator<A, type>::type deallocator;
757
758 public:
759     sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
760         : deleter_(allocator),
761           allocator_(allocator) { }
762
763     sp_counted_impl_pda(P, const A& allocator)
764         : deleter_(allocator) { }
765
766     void dispose() {
767         deleter_(0);
768     }
769
770     void destroy() {
771         deallocator allocator(allocator_);
772         this->~type();
773         allocator.deallocate(this, 1);
774     }
775
776     void* get_deleter(const sp_typeinfo&) {
777         return &reinterpret_cast<char&>(deleter_);
778     }
779
780     void* get_untyped_deleter() {
781         return &reinterpret_cast<char&>(deleter_);
782     }
783
784 private:
785     deleter_type deleter_;
786     A allocator_;
787 };
788
789 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
790 template<class P, class T, std::size_t N, class U, class A>
791 class sp_counted_impl_pda<P, sp_size_array_destroyer<T, N, U>, A>
792     : public sp_counted_base {
793 public:
794     typedef sp_size_array_destroyer<T, N, U> deleter_type;
795
796 private:
797     typedef sp_counted_impl_pda<P, deleter_type, A> type;
798     typedef typename sp_bind_allocator<A, type>::type deallocator;
799
800 public:
801     sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
802         : deleter_(allocator) { }
803
804     sp_counted_impl_pda(P, const A& allocator)
805         : deleter_(allocator) { }
806
807     void dispose() {
808         deleter_(0);
809     }
810
811     void destroy() {
812         deallocator allocator(deleter_.allocator());
813         this->~type();
814         allocator.deallocate(this, 1);
815     }
816
817     void* get_deleter(const sp_typeinfo&) {
818         return &reinterpret_cast<char&>(deleter_);
819     }
820
821     void* get_untyped_deleter() {
822         return &reinterpret_cast<char&>(deleter_);
823     }
824
825 private:
826     deleter_type deleter_;
827 };
828 #endif
829
830 template<class P, class T, class A>
831 class sp_counted_impl_pda<P, sp_array_deleter<T>,
832     sp_array_allocator<T, A> >
833     : public sp_counted_base {
834 public:
835     typedef sp_array_deleter<T> deleter_type;
836     typedef sp_array_allocator<T, A> allocator_type;
837
838 private:
839     typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
840     typedef sp_array_allocator<T,
841         typename sp_bind_allocator<A, type>::type> deallocator;
842
843 public:
844     sp_counted_impl_pda(P, const deleter_type&,
845         const allocator_type& allocator)
846         : deleter_(allocator),
847           allocator_(allocator.allocator()) { }
848
849     sp_counted_impl_pda(P, const allocator_type& allocator)
850         : deleter_(allocator),
851           allocator_(allocator.allocator()) { }
852
853     void dispose() {
854         deleter_(0);
855     }
856
857     void destroy() {
858         deallocator allocator(allocator_, deleter_.size());
859         this->~type();
860         allocator.deallocate(this, 1);
861     }
862
863     void* get_deleter(const sp_typeinfo&) {
864         return &reinterpret_cast<char&>(deleter_);
865     }
866
867     void* get_untyped_deleter() {
868         return &reinterpret_cast<char&>(deleter_);
869     }
870
871 private:
872     deleter_type deleter_;
873     A allocator_;
874 };
875
876 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
877 template<class P, class T, class U, class A>
878 class sp_counted_impl_pda<P, sp_array_destroyer<T, U>,
879     sp_array_allocator<T, A> >
880     : public sp_counted_base {
881 public:
882     typedef sp_array_destroyer<T, U> deleter_type;
883     typedef sp_array_allocator<T, A> allocator_type;
884
885 private:
886     typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
887     typedef sp_array_allocator<T,
888         typename sp_bind_allocator<A, type>::type> deallocator;
889
890 public:
891     sp_counted_impl_pda(P, const deleter_type&,
892         const allocator_type& allocator)
893         : deleter_(allocator) { }
894
895     sp_counted_impl_pda(P, const allocator_type& allocator)
896         : deleter_(allocator) { }
897
898     void dispose() {
899         deleter_(0);
900     }
901
902     void destroy() {
903         deallocator allocator(deleter_.allocator(), deleter_.size());
904         this->~type();
905         allocator.deallocate(this, 1);
906     }
907
908     void* get_deleter(const sp_typeinfo&) {
909         return &reinterpret_cast<char&>(deleter_);
910     }
911
912     void* get_untyped_deleter() {
913         return &reinterpret_cast<char&>(deleter_);
914     }
915
916 private:
917     deleter_type deleter_;
918 };
919 #endif
920
921 } /* detail */
922
923 template<class T, class A>
924 inline typename detail::sp_if_size_array<T>::type
925 allocate_shared(const A& allocator)
926 {
927     typedef typename detail::sp_array_element<T>::type type;
928     typedef typename detail::sp_array_scalar<T>::type scalar;
929     typedef typename detail::sp_select_size_deleter<A, scalar,
930         detail::sp_array_count<T>::value>::type deleter;
931     shared_ptr<T> result(static_cast<type*>(0),
932         detail::sp_inplace_tag<deleter>(), allocator);
933     deleter* state = detail::sp_get_deleter<deleter>(result);
934     void* start = state->construct();
935     return shared_ptr<T>(result, static_cast<type*>(start));
936 }
937
938 template<class T, class A>
939 inline typename detail::sp_if_size_array<T>::type
940 allocate_shared(const A& allocator,
941     const typename detail::sp_array_element<T>::type& value)
942 {
943     typedef typename detail::sp_array_element<T>::type type;
944     typedef typename detail::sp_array_scalar<T>::type scalar;
945     typedef typename detail::sp_select_size_deleter<A, scalar,
946         detail::sp_array_count<T>::value>::type deleter;
947     shared_ptr<T> result(static_cast<type*>(0),
948         detail::sp_inplace_tag<deleter>(), allocator);
949     deleter* state = detail::sp_get_deleter<deleter>(result);
950     void* start = state->construct(reinterpret_cast<const
951         scalar*>(&value), detail::sp_array_count<type>::value);
952     return shared_ptr<T>(result, static_cast<type*>(start));
953 }
954
955 template<class T, class A>
956 inline typename detail::sp_if_size_array<T>::type
957 allocate_shared_noinit(const A& allocator)
958 {
959     typedef typename detail::sp_array_element<T>::type type;
960     typedef typename detail::sp_array_scalar<T>::type scalar;
961     typedef detail::sp_size_array_deleter<scalar,
962         detail::sp_array_count<T>::value> deleter;
963     shared_ptr<T> result(static_cast<type*>(0),
964         detail::sp_inplace_tag<deleter>(), allocator);
965     deleter* state = detail::sp_get_deleter<deleter>(result);
966     void* start = state->construct_default();
967     return shared_ptr<T>(result, static_cast<type*>(start));
968 }
969
970 template<class T, class A>
971 inline typename detail::sp_if_array<T>::type
972 allocate_shared(const A& allocator, std::size_t count)
973 {
974     typedef typename detail::sp_array_element<T>::type type;
975     typedef typename detail::sp_array_scalar<T>::type scalar;
976     typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
977     std::size_t size = count * detail::sp_array_count<type>::value;
978     void* start;
979     shared_ptr<T> result(static_cast<type*>(0),
980         detail::sp_inplace_tag<deleter>(),
981         detail::sp_array_allocator<scalar, A>(allocator, size, &start));
982     deleter* state = detail::sp_get_deleter<deleter>(result);
983     state->construct(static_cast<scalar*>(start));
984     return shared_ptr<T>(result, static_cast<type*>(start));
985 }
986
987 template<class T, class A>
988 inline typename detail::sp_if_array<T>::type
989 allocate_shared(const A& allocator, std::size_t count,
990     const typename detail::sp_array_element<T>::type& value)
991 {
992     typedef typename detail::sp_array_element<T>::type type;
993     typedef typename detail::sp_array_scalar<T>::type scalar;
994     typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
995     std::size_t size = count * detail::sp_array_count<type>::value;
996     void* start;
997     shared_ptr<T> result(static_cast<type*>(0),
998         detail::sp_inplace_tag<deleter>(),
999         detail::sp_array_allocator<scalar, A>(allocator, size, &start));
1000     deleter* state = detail::sp_get_deleter<deleter>(result);
1001     state->construct(static_cast<scalar*>(start),
1002         reinterpret_cast<const scalar*>(&value),
1003         detail::sp_array_count<type>::value);
1004     return shared_ptr<T>(result, static_cast<type*>(start));
1005 }
1006
1007 template<class T, class A>
1008 inline typename detail::sp_if_array<T>::type
1009 allocate_shared_noinit(const A& allocator, std::size_t count)
1010 {
1011     typedef typename detail::sp_array_element<T>::type type;
1012     typedef typename detail::sp_array_scalar<T>::type scalar;
1013     typedef detail::sp_array_deleter<scalar> deleter;
1014     std::size_t size = count * detail::sp_array_count<type>::value;
1015     void* start;
1016     shared_ptr<T> result(static_cast<type*>(0),
1017         detail::sp_inplace_tag<deleter>(),
1018         detail::sp_array_allocator<scalar, A>(allocator, size, &start));
1019     deleter* state = detail::sp_get_deleter<deleter>(result);
1020     state->construct_default(static_cast<scalar*>(start));
1021     return shared_ptr<T>(result, static_cast<type*>(start));
1022 }
1023
1024 } /* boost */
1025
1026 #endif