allocate_shared_array.hpp 19 KB

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