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/alignment_of.hpp> |
13 | #include <boost/type_traits/has_trivial_assign.hpp> |
14 | #include <boost/type_traits/has_trivial_constructor.hpp> |
15 | #include <boost/type_traits/has_trivial_destructor.hpp> |
16 | #include <boost/type_traits/type_with_alignment.hpp> |
17 | |
18 | namespace boost { |
19 | namespace detail { |
20 | |
21 | template<class> |
22 | struct sp_if_array { }; |
23 | |
24 | template<class T> |
25 | struct sp_if_array<T[]> { |
26 | typedef boost::shared_ptr<T[]> type; |
27 | }; |
28 | |
29 | template<class> |
30 | struct sp_if_size_array { }; |
31 | |
32 | template<class T, std::size_t N> |
33 | struct sp_if_size_array<T[N]> { |
34 | typedef boost::shared_ptr<T[N]> type; |
35 | }; |
36 | |
37 | template<class> |
38 | struct sp_array_element { }; |
39 | |
40 | template<class T> |
41 | struct sp_array_element<T[]> { |
42 | typedef T type; |
43 | }; |
44 | |
45 | template<class T, std::size_t N> |
46 | struct sp_array_element<T[N]> { |
47 | typedef T type; |
48 | }; |
49 | |
50 | template<class T> |
51 | struct sp_array_scalar { |
52 | typedef T type; |
53 | }; |
54 | |
55 | template<class T, std::size_t N> |
56 | struct sp_array_scalar<T[N]> { |
57 | typedef typename sp_array_scalar<T>::type type; |
58 | }; |
59 | |
60 | template<class T, std::size_t N> |
61 | struct sp_array_scalar<const T[N]> { |
62 | typedef typename sp_array_scalar<T>::type type; |
63 | }; |
64 | |
65 | template<class T, std::size_t N> |
66 | struct sp_array_scalar<volatile T[N]> { |
67 | typedef typename sp_array_scalar<T>::type type; |
68 | }; |
69 | |
70 | template<class T, std::size_t N> |
71 | struct sp_array_scalar<const volatile T[N]> { |
72 | typedef typename sp_array_scalar<T>::type type; |
73 | }; |
74 | |
75 | template<class T> |
76 | struct sp_array_scalar<T[]> { |
77 | typedef typename sp_array_scalar<T>::type type; |
78 | }; |
79 | |
80 | template<class T> |
81 | struct sp_array_scalar<const T[]> { |
82 | typedef typename sp_array_scalar<T>::type type; |
83 | }; |
84 | |
85 | template<class T> |
86 | struct sp_array_scalar<volatile T[]> { |
87 | typedef typename sp_array_scalar<T>::type type; |
88 | }; |
89 | |
90 | template<class T> |
91 | struct sp_array_scalar<const volatile T[]> { |
92 | typedef typename sp_array_scalar<T>::type type; |
93 | }; |
94 | |
95 | template<class T> |
96 | struct sp_array_count { |
97 | enum { |
98 | value = 1 |
99 | }; |
100 | }; |
101 | |
102 | template<class T, std::size_t N> |
103 | struct sp_array_count<T[N]> { |
104 | enum { |
105 | value = N * sp_array_count<T>::value |
106 | }; |
107 | }; |
108 | |
109 | template<std::size_t N, std::size_t M> |
110 | struct sp_max_size { |
111 | enum { |
112 | value = N < M ? M : N |
113 | }; |
114 | }; |
115 | |
116 | template<std::size_t N, std::size_t M> |
117 | struct sp_align_up { |
118 | enum { |
119 | value = (N + M - 1) & ~(M - 1) |
120 | }; |
121 | }; |
122 | |
123 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
124 | template<class A, class T> |
125 | struct sp_bind_allocator { |
126 | typedef typename std::allocator_traits<A>::template rebind_alloc<T> type; |
127 | }; |
128 | #else |
129 | template<class A, class T> |
130 | struct sp_bind_allocator { |
131 | typedef typename A::template rebind<T>::other type; |
132 | }; |
133 | #endif |
134 | |
135 | template<class T> |
136 | BOOST_CONSTEXPR inline std::size_t |
137 | sp_objects(std::size_t size) BOOST_SP_NOEXCEPT |
138 | { |
139 | return (size + sizeof(T) - 1) / sizeof(T); |
140 | } |
141 | |
142 | template<bool, class = void> |
143 | struct sp_enable { }; |
144 | |
145 | template<class T> |
146 | struct sp_enable<true, T> { |
147 | typedef T type; |
148 | }; |
149 | |
150 | template<bool E, class A, class T> |
151 | inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type |
152 | sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } |
153 | |
154 | template<bool E, class A, class T> |
155 | inline typename sp_enable<!E && |
156 | !boost::has_trivial_destructor<T>::value>::type |
157 | sp_array_destroy(A&, T* start, std::size_t size) |
158 | { |
159 | while (size > 0) { |
160 | start[--size].~T(); |
161 | } |
162 | } |
163 | |
164 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
165 | template<bool E, class A, class T> |
166 | inline typename sp_enable<E>::type |
167 | sp_array_destroy(A& allocator, T* start, std::size_t size) |
168 | { |
169 | while (size > 0) { |
170 | std::allocator_traits<A>::destroy(allocator, start + --size); |
171 | } |
172 | } |
173 | #endif |
174 | |
175 | template<bool E, class A, class T> |
176 | inline typename sp_enable<!E && |
177 | boost::has_trivial_constructor<T>::value && |
178 | boost::has_trivial_assign<T>::value>::type |
179 | sp_array_construct(A&, T* start, std::size_t size) |
180 | { |
181 | for (std::size_t i = 0; i < size; ++i) { |
182 | start[i] = T(); |
183 | } |
184 | } |
185 | |
186 | template<bool E, class A, class T> |
187 | inline typename sp_enable<!E && |
188 | boost::has_trivial_constructor<T>::value && |
189 | boost::has_trivial_assign<T>::value>::type |
190 | sp_array_construct(A&, T* start, std::size_t size, const T* list, |
191 | std::size_t count) |
192 | { |
193 | for (std::size_t i = 0; i < size; ++i) { |
194 | start[i] = list[i % count]; |
195 | } |
196 | } |
197 | |
198 | #if !defined(BOOST_NO_EXCEPTIONS) |
199 | template<bool E, class A, class T> |
200 | inline typename sp_enable<!E && |
201 | !(boost::has_trivial_constructor<T>::value && |
202 | boost::has_trivial_assign<T>::value)>::type |
203 | sp_array_construct(A& none, T* start, std::size_t size) |
204 | { |
205 | std::size_t i = 0; |
206 | try { |
207 | for (; i < size; ++i) { |
208 | ::new(static_cast<void*>(start + i)) T(); |
209 | } |
210 | } catch (...) { |
211 | sp_array_destroy<E>(none, start, i); |
212 | throw; |
213 | } |
214 | } |
215 | |
216 | template<bool E, class A, class T> |
217 | inline typename sp_enable<!E && |
218 | !(boost::has_trivial_constructor<T>::value && |
219 | boost::has_trivial_assign<T>::value)>::type |
220 | sp_array_construct(A& none, T* start, std::size_t size, const T* list, |
221 | std::size_t count) |
222 | { |
223 | std::size_t i = 0; |
224 | try { |
225 | for (; i < size; ++i) { |
226 | ::new(static_cast<void*>(start + i)) T(list[i % count]); |
227 | } |
228 | } catch (...) { |
229 | sp_array_destroy<E>(none, start, i); |
230 | throw; |
231 | } |
232 | } |
233 | #else |
234 | template<bool E, class A, class T> |
235 | inline typename sp_enable<!E && |
236 | !(boost::has_trivial_constructor<T>::value && |
237 | boost::has_trivial_assign<T>::value)>::type |
238 | sp_array_construct(A&, T* start, std::size_t size) |
239 | { |
240 | for (std::size_t i = 0; i < size; ++i) { |
241 | ::new(static_cast<void*>(start + i)) T(); |
242 | } |
243 | } |
244 | |
245 | template<bool E, class A, class T> |
246 | inline typename sp_enable<!E && |
247 | !(boost::has_trivial_constructor<T>::value && |
248 | boost::has_trivial_assign<T>::value)>::type |
249 | sp_array_construct(A&, T* start, std::size_t size, const T* list, |
250 | std::size_t count) |
251 | { |
252 | for (std::size_t i = 0; i < size; ++i) { |
253 | ::new(static_cast<void*>(start + i)) T(list[i % count]); |
254 | } |
255 | } |
256 | #endif |
257 | |
258 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
259 | #if !defined(BOOST_NO_EXCEPTIONS) |
260 | template<bool E, class A, class T> |
261 | inline typename sp_enable<E>::type |
262 | sp_array_construct(A& allocator, T* start, std::size_t size) |
263 | { |
264 | std::size_t i = 0; |
265 | try { |
266 | for (i = 0; i < size; ++i) { |
267 | std::allocator_traits<A>::construct(allocator, start + i); |
268 | } |
269 | } catch (...) { |
270 | sp_array_destroy<E>(allocator, start, i); |
271 | throw; |
272 | } |
273 | } |
274 | |
275 | template<bool E, class A, class T> |
276 | inline typename sp_enable<E>::type |
277 | sp_array_construct(A& allocator, T* start, std::size_t size, const T* list, |
278 | std::size_t count) |
279 | { |
280 | std::size_t i = 0; |
281 | try { |
282 | for (i = 0; i < size; ++i) { |
283 | std::allocator_traits<A>::construct(allocator, start + i, |
284 | list[i % count]); |
285 | } |
286 | } catch (...) { |
287 | sp_array_destroy<E>(allocator, start, i); |
288 | throw; |
289 | } |
290 | } |
291 | #else |
292 | template<bool E, class A, class T> |
293 | inline typename sp_enable<E>::type |
294 | sp_array_construct(A& allocator, T* start, std::size_t size) |
295 | { |
296 | for (std::size_t i = 0; i < size; ++i) { |
297 | std::allocator_traits<A>::construct(allocator, start + i); |
298 | } |
299 | } |
300 | |
301 | template<bool E, class A, class T> |
302 | inline typename sp_enable<E>::type |
303 | sp_array_construct(A& allocator, T* start, std::size_t size, const T* list, |
304 | std::size_t count) |
305 | { |
306 | for (std::size_t i = 0; i < size; ++i) { |
307 | std::allocator_traits<A>::construct(allocator, start + i, |
308 | list[i % count]); |
309 | } |
310 | } |
311 | #endif |
312 | #endif |
313 | |
314 | template<class A, class T> |
315 | inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type |
316 | sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } |
317 | |
318 | #if !defined(BOOST_NO_EXCEPTIONS) |
319 | template<class A, class T> |
320 | inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type |
321 | sp_array_default(A& none, T* start, std::size_t size) |
322 | { |
323 | std::size_t i = 0; |
324 | try { |
325 | for (; i < size; ++i) { |
326 | ::new(static_cast<void*>(start + i)) T; |
327 | } |
328 | } catch (...) { |
329 | sp_array_destroy<false>(none, start, i); |
330 | throw; |
331 | } |
332 | } |
333 | #else |
334 | template<bool E, class A, class T> |
335 | inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type |
336 | sp_array_default(A&, T* start, std::size_t size) |
337 | { |
338 | for (std::size_t i = 0; i < size; ++i) { |
339 | ::new(static_cast<void*>(start + i)) T; |
340 | } |
341 | } |
342 | #endif |
343 | |
344 | template<class A> |
345 | class sp_array_state { |
346 | public: |
347 | typedef A type; |
348 | |
349 | template<class U> |
350 | sp_array_state(const U& allocator, std::size_t size) BOOST_SP_NOEXCEPT |
351 | : allocator_(allocator), |
352 | size_(size) { } |
353 | |
354 | A& allocator() BOOST_SP_NOEXCEPT { |
355 | return allocator_; |
356 | } |
357 | |
358 | std::size_t size() const BOOST_SP_NOEXCEPT { |
359 | return size_; |
360 | } |
361 | |
362 | private: |
363 | A allocator_; |
364 | std::size_t size_; |
365 | }; |
366 | |
367 | template<class A, std::size_t N> |
368 | class sp_size_array_state { |
369 | public: |
370 | typedef A type; |
371 | |
372 | template<class U> |
373 | sp_size_array_state(const U& allocator, std::size_t) BOOST_SP_NOEXCEPT |
374 | : allocator_(allocator) { } |
375 | |
376 | A& allocator() BOOST_SP_NOEXCEPT { |
377 | return allocator_; |
378 | } |
379 | |
380 | BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT { |
381 | return N; |
382 | } |
383 | |
384 | private: |
385 | A allocator_; |
386 | }; |
387 | |
388 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
389 | template<class A> |
390 | struct sp_use_construct { |
391 | enum { |
392 | value = true |
393 | }; |
394 | }; |
395 | |
396 | template<class T> |
397 | struct sp_use_construct<std::allocator<T> > { |
398 | enum { |
399 | value = false |
400 | }; |
401 | }; |
402 | #else |
403 | template<class> |
404 | struct sp_use_construct { |
405 | enum { |
406 | value = false |
407 | }; |
408 | }; |
409 | #endif |
410 | |
411 | template<class T, class U> |
412 | struct sp_array_alignment { |
413 | enum { |
414 | value = sp_max_size<boost::alignment_of<T>::value, |
415 | boost::alignment_of<U>::value>::value |
416 | }; |
417 | }; |
418 | |
419 | template<class T, class U> |
420 | struct sp_array_offset { |
421 | enum { |
422 | value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value |
423 | }; |
424 | }; |
425 | |
426 | template<class T, class U> |
427 | struct sp_array_storage { |
428 | enum { |
429 | value = sp_array_alignment<T, U>::value |
430 | }; |
431 | typedef typename boost::type_with_alignment<value>::type type; |
432 | }; |
433 | |
434 | template<class T, class U> |
435 | inline U* |
436 | sp_array_start(void* base) BOOST_SP_NOEXCEPT |
437 | { |
438 | enum { |
439 | size = sp_array_offset<T, U>::value |
440 | }; |
441 | return reinterpret_cast<U*>(static_cast<char*>(base) + size); |
442 | } |
443 | |
444 | template<class A, class T> |
445 | class sp_array_creator { |
446 | typedef typename A::value_type scalar; |
447 | |
448 | enum { |
449 | offset = sp_array_offset<T, scalar>::value |
450 | }; |
451 | |
452 | typedef typename sp_array_storage<T, scalar>::type type; |
453 | |
454 | public: |
455 | template<class U> |
456 | sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT |
457 | : other_(other), |
458 | size_(sp_objects<type>(offset + sizeof(scalar) * size)) { } |
459 | |
460 | T* create() { |
461 | return reinterpret_cast<T*>(other_.allocate(size_)); |
462 | } |
463 | |
464 | void destroy(T* base) { |
465 | other_.deallocate(reinterpret_cast<type*>(base), size_); |
466 | } |
467 | |
468 | private: |
469 | typename sp_bind_allocator<A, type>::type other_; |
470 | std::size_t size_; |
471 | }; |
472 | |
473 | struct sp_default { }; |
474 | |
475 | template<class T, bool E = sp_use_construct<T>::value> |
476 | class sp_array_base |
477 | : public sp_counted_base { |
478 | typedef typename T::type allocator; |
479 | |
480 | public: |
481 | typedef typename allocator::value_type type; |
482 | |
483 | template<class A> |
484 | sp_array_base(const A& other, std::size_t size, type* start) |
485 | : state_(other, size) { |
486 | sp_array_construct<E>(state_.allocator(), start, state_.size()); |
487 | } |
488 | |
489 | template<class A> |
490 | sp_array_base(const A& other, std::size_t size, const type* list, |
491 | std::size_t count, type* start) |
492 | : state_(other, size) { |
493 | sp_array_construct<E>(state_.allocator(), start, state_.size(), list, |
494 | count); |
495 | } |
496 | |
497 | template<class A> |
498 | sp_array_base(sp_default, const A& other, std::size_t size, type* start) |
499 | : state_(other, size) { |
500 | sp_array_default(state_.allocator(), start, state_.size()); |
501 | } |
502 | |
503 | T& state() BOOST_SP_NOEXCEPT { |
504 | return state_; |
505 | } |
506 | |
507 | virtual void dispose() { |
508 | sp_array_destroy<E>(state_.allocator(), |
509 | sp_array_start<sp_array_base, type>(this), state_.size()); |
510 | } |
511 | |
512 | virtual void destroy() { |
513 | sp_array_creator<allocator, sp_array_base> other(state_.allocator(), |
514 | state_.size()); |
515 | this->~sp_array_base(); |
516 | other.destroy(this); |
517 | } |
518 | |
519 | virtual void* get_deleter(const sp_typeinfo&) { |
520 | return 0; |
521 | } |
522 | |
523 | virtual void* get_local_deleter(const sp_typeinfo&) { |
524 | return 0; |
525 | } |
526 | |
527 | virtual void* get_untyped_deleter() { |
528 | return 0; |
529 | } |
530 | |
531 | private: |
532 | T state_; |
533 | }; |
534 | |
535 | template<class A, class T> |
536 | struct sp_array_result { |
537 | public: |
538 | template<class U> |
539 | sp_array_result(const U& other, std::size_t size) |
540 | : creator_(other, size), |
541 | result_(creator_.create()) { } |
542 | |
543 | ~sp_array_result() { |
544 | if (result_) { |
545 | creator_.destroy(result_); |
546 | } |
547 | } |
548 | |
549 | T* get() const { |
550 | return result_; |
551 | } |
552 | |
553 | void release() { |
554 | result_ = 0; |
555 | } |
556 | |
557 | private: |
558 | sp_array_result(const sp_array_result&); |
559 | sp_array_result& operator=(const sp_array_result&); |
560 | |
561 | sp_array_creator<A, T> creator_; |
562 | T* result_; |
563 | }; |
564 | |
565 | } /* detail */ |
566 | |
567 | template<class T, class A> |
568 | inline typename detail::sp_if_array<T>::type |
569 | allocate_shared(const A& allocator, std::size_t count) |
570 | { |
571 | typedef typename detail::sp_array_element<T>::type type; |
572 | typedef typename detail::sp_array_scalar<T>::type scalar; |
573 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
574 | typedef detail::sp_array_state<other> state; |
575 | typedef detail::sp_array_base<state> base; |
576 | std::size_t size = count * detail::sp_array_count<type>::value; |
577 | detail::sp_array_result<other, base> result(allocator, size); |
578 | detail::sp_counted_base* node = result.get(); |
579 | scalar* start = detail::sp_array_start<base, scalar>(node); |
580 | ::new(static_cast<void*>(node)) base(allocator, size, start); |
581 | result.release(); |
582 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
583 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
584 | } |
585 | |
586 | template<class T, class A> |
587 | inline typename detail::sp_if_size_array<T>::type |
588 | allocate_shared(const A& allocator) |
589 | { |
590 | enum { |
591 | size = detail::sp_array_count<T>::value |
592 | }; |
593 | typedef typename detail::sp_array_element<T>::type type; |
594 | typedef typename detail::sp_array_scalar<T>::type scalar; |
595 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
596 | typedef detail::sp_size_array_state<other, size> state; |
597 | typedef detail::sp_array_base<state> base; |
598 | detail::sp_array_result<other, base> result(allocator, size); |
599 | detail::sp_counted_base* node = result.get(); |
600 | scalar* start = detail::sp_array_start<base, scalar>(node); |
601 | ::new(static_cast<void*>(node)) base(allocator, size, start); |
602 | result.release(); |
603 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
604 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
605 | } |
606 | |
607 | template<class T, class A> |
608 | inline typename detail::sp_if_array<T>::type |
609 | allocate_shared(const A& allocator, std::size_t count, |
610 | const typename detail::sp_array_element<T>::type& value) |
611 | { |
612 | typedef typename detail::sp_array_element<T>::type type; |
613 | typedef typename detail::sp_array_scalar<T>::type scalar; |
614 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
615 | typedef detail::sp_array_state<other> state; |
616 | typedef detail::sp_array_base<state> base; |
617 | std::size_t size = count * detail::sp_array_count<type>::value; |
618 | detail::sp_array_result<other, base> result(allocator, size); |
619 | detail::sp_counted_base* node = result.get(); |
620 | scalar* start = detail::sp_array_start<base, scalar>(node); |
621 | ::new(static_cast<void*>(node)) base(allocator, size, |
622 | reinterpret_cast<const scalar*>(&value), |
623 | detail::sp_array_count<type>::value, start); |
624 | result.release(); |
625 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
626 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
627 | } |
628 | |
629 | template<class T, class A> |
630 | inline typename detail::sp_if_size_array<T>::type |
631 | allocate_shared(const A& allocator, |
632 | const typename detail::sp_array_element<T>::type& value) |
633 | { |
634 | enum { |
635 | size = detail::sp_array_count<T>::value |
636 | }; |
637 | typedef typename detail::sp_array_element<T>::type type; |
638 | typedef typename detail::sp_array_scalar<T>::type scalar; |
639 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
640 | typedef detail::sp_size_array_state<other, size> state; |
641 | typedef detail::sp_array_base<state> base; |
642 | detail::sp_array_result<other, base> result(allocator, size); |
643 | detail::sp_counted_base* node = result.get(); |
644 | scalar* start = detail::sp_array_start<base, scalar>(node); |
645 | ::new(static_cast<void*>(node)) base(allocator, size, |
646 | reinterpret_cast<const scalar*>(&value), |
647 | detail::sp_array_count<type>::value, start); |
648 | result.release(); |
649 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
650 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
651 | } |
652 | |
653 | template<class T, class A> |
654 | inline typename detail::sp_if_array<T>::type |
655 | allocate_shared_noinit(const A& allocator, std::size_t count) |
656 | { |
657 | typedef typename detail::sp_array_element<T>::type type; |
658 | typedef typename detail::sp_array_scalar<T>::type scalar; |
659 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
660 | typedef detail::sp_array_state<other> state; |
661 | typedef detail::sp_array_base<state, false> base; |
662 | std::size_t size = count * detail::sp_array_count<type>::value; |
663 | detail::sp_array_result<other, base> result(allocator, size); |
664 | detail::sp_counted_base* node = result.get(); |
665 | scalar* start = detail::sp_array_start<base, scalar>(node); |
666 | ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, |
667 | size, start); |
668 | result.release(); |
669 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
670 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
671 | } |
672 | |
673 | template<class T, class A> |
674 | inline typename detail::sp_if_size_array<T>::type |
675 | allocate_shared_noinit(const A& allocator) |
676 | { |
677 | enum { |
678 | size = detail::sp_array_count<T>::value |
679 | }; |
680 | typedef typename detail::sp_array_element<T>::type type; |
681 | typedef typename detail::sp_array_scalar<T>::type scalar; |
682 | typedef typename detail::sp_bind_allocator<A, scalar>::type other; |
683 | typedef detail::sp_size_array_state<other, size> state; |
684 | typedef detail::sp_array_base<state, false> base; |
685 | detail::sp_array_result<other, base> result(allocator, size); |
686 | detail::sp_counted_base* node = result.get(); |
687 | scalar* start = detail::sp_array_start<base, scalar>(node); |
688 | ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, |
689 | size, start); |
690 | result.release(); |
691 | return shared_ptr<T>(detail::sp_internal_constructor_tag(), |
692 | reinterpret_cast<type*>(start), detail::shared_count(node)); |
693 | } |
694 | |
695 | } /* boost */ |
696 | |
697 | #endif |
698 | |