make_shared_array.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Copyright (c) 2012 Glen Joseph Fernandes
  3. * glenfe at live dot com
  4. *
  5. * Distributed under the Boost Software License,
  6. * Version 1.0. (See accompanying file LICENSE_1_0.txt
  7. * or copy at http://boost.org/LICENSE_1_0.txt)
  8. */
  9. #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
  10. #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
  11. #include <boost/smart_ptr/shared_ptr.hpp>
  12. #include <boost/smart_ptr/detail/array_deleter.hpp>
  13. #include <boost/smart_ptr/detail/array_traits.hpp>
  14. #include <boost/smart_ptr/detail/make_array_helper.hpp>
  15. #include <boost/smart_ptr/detail/sp_if_array.hpp>
  16. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  17. #include <initializer_list>
  18. #endif
  19. namespace boost {
  20. template<typename T>
  21. inline typename boost::detail::sp_if_array<T>::type
  22. make_shared(std::size_t size) {
  23. typedef typename boost::detail::array_inner<T>::type T1;
  24. typedef typename boost::detail::array_base<T1>::type T2;
  25. T1* p1 = 0;
  26. T2* p2 = 0;
  27. std::size_t n1 = size * boost::detail::array_total<T1>::size;
  28. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  29. boost::detail::array_deleter<T2[]> d1(n1);
  30. boost::shared_ptr<T> s1(p1, d1, a1);
  31. typedef boost::detail::array_deleter<T2[]>* D2;
  32. p1 = reinterpret_cast<T1*>(p2);
  33. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  34. d2->init(p2);
  35. return boost::shared_ptr<T>(s1, p1);
  36. }
  37. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  38. template<typename T, typename... Args>
  39. inline typename boost::detail::sp_if_array<T>::type
  40. make_shared(std::size_t size, Args&&... args) {
  41. typedef typename boost::detail::array_inner<T>::type T1;
  42. typedef typename boost::detail::array_base<T1>::type T2;
  43. T1* p1 = 0;
  44. T2* p2 = 0;
  45. std::size_t n1 = size * boost::detail::array_total<T1>::size;
  46. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  47. boost::detail::array_deleter<T2[]> d1(n1);
  48. boost::shared_ptr<T> s1(p1, d1, a1);
  49. typedef boost::detail::array_deleter<T2[]>* D2;
  50. p1 = reinterpret_cast<T1*>(p2);
  51. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  52. d2->init(p2, boost::detail::sp_forward<Args>(args)...);
  53. return boost::shared_ptr<T>(s1, p1);
  54. }
  55. template<typename T, typename... Args>
  56. inline typename boost::detail::sp_if_size_array<T>::type
  57. make_shared(Args&&... args) {
  58. typedef typename boost::detail::array_inner<T>::type T1;
  59. typedef typename boost::detail::array_base<T1>::type T2;
  60. enum {
  61. N = boost::detail::array_total<T>::size
  62. };
  63. T1* p1 = 0;
  64. T2* p2 = 0;
  65. boost::detail::make_array_helper<T2[N]> a1(&p2);
  66. boost::detail::array_deleter<T2[N]> d1;
  67. boost::shared_ptr<T> s1(p1, d1, a1);
  68. typedef boost::detail::array_deleter<T2[N]>* D2;
  69. p1 = reinterpret_cast<T1*>(p2);
  70. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  71. d2->init(p2, boost::detail::sp_forward<Args>(args)...);
  72. return boost::shared_ptr<T>(s1, p1);
  73. }
  74. #endif
  75. #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
  76. template<typename T>
  77. inline typename boost::detail::sp_if_size_array<T>::type
  78. make_shared(const T& list) {
  79. typedef typename boost::detail::array_inner<T>::type T1;
  80. typedef typename boost::detail::array_base<T1>::type T2;
  81. typedef const T2 T3;
  82. enum {
  83. N = boost::detail::array_total<T>::size
  84. };
  85. T1* p1 = 0;
  86. T2* p2 = 0;
  87. T3* p3 = 0;
  88. boost::detail::make_array_helper<T2[N]> a1(&p2);
  89. boost::detail::array_deleter<T2[N]> d1;
  90. boost::shared_ptr<T> s1(p1, d1, a1);
  91. typedef boost::detail::array_deleter<T2[N]>* D2;
  92. p3 = reinterpret_cast<T3*>(list);
  93. p1 = reinterpret_cast<T1*>(p2);
  94. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  95. d2->init_list(p2, p3);
  96. return boost::shared_ptr<T>(s1, p1);
  97. }
  98. template<typename T>
  99. inline typename boost::detail::sp_if_array<T>::type
  100. make_shared(std::size_t size,
  101. const typename boost::detail::array_inner<T>::type& list) {
  102. typedef typename boost::detail::array_inner<T>::type T1;
  103. typedef typename boost::detail::array_base<T1>::type T2;
  104. typedef const T2 T3;
  105. enum {
  106. M = boost::detail::array_total<T1>::size
  107. };
  108. T1* p1 = 0;
  109. T2* p2 = 0;
  110. T3* p3 = 0;
  111. std::size_t n1 = M * size;
  112. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  113. boost::detail::array_deleter<T2[]> d1(n1);
  114. boost::shared_ptr<T> s1(p1, d1, a1);
  115. typedef boost::detail::array_deleter<T2[]>* D2;
  116. p3 = reinterpret_cast<T3*>(list);
  117. p1 = reinterpret_cast<T1*>(p2);
  118. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  119. d2->template init_list<M>(p2, p3);
  120. return boost::shared_ptr<T>(s1, p1);
  121. }
  122. template<typename T>
  123. inline typename boost::detail::sp_if_size_array<T>::type
  124. make_shared(const typename boost::detail::array_inner<T>::type& list) {
  125. typedef typename boost::detail::array_inner<T>::type T1;
  126. typedef typename boost::detail::array_base<T1>::type T2;
  127. typedef const T2 T3;
  128. enum {
  129. M = boost::detail::array_total<T1>::size,
  130. N = boost::detail::array_total<T>::size
  131. };
  132. T1* p1 = 0;
  133. T2* p2 = 0;
  134. T3* p3 = 0;
  135. boost::detail::make_array_helper<T2[N]> a1(&p2);
  136. boost::detail::array_deleter<T2[N]> d1;
  137. boost::shared_ptr<T> s1(p1, d1, a1);
  138. typedef boost::detail::array_deleter<T2[N]>* D2;
  139. p3 = reinterpret_cast<T3*>(list);
  140. p1 = reinterpret_cast<T1*>(p2);
  141. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  142. d2->template init_list<M>(p2, p3);
  143. return boost::shared_ptr<T>(s1, p1);
  144. }
  145. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  146. template<typename T>
  147. inline typename boost::detail::sp_if_array<T>::type
  148. make_shared(std::initializer_list<typename boost::detail::array_inner<T>::type> list) {
  149. typedef typename boost::detail::array_inner<T>::type T1;
  150. typedef typename boost::detail::array_base<T1>::type T2;
  151. typedef const T2 T3;
  152. T1* p1 = 0;
  153. T2* p2 = 0;
  154. T3* p3 = 0;
  155. std::size_t n1 = list.size() * boost::detail::array_total<T1>::size;
  156. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  157. boost::detail::array_deleter<T2[]> d1(n1);
  158. boost::shared_ptr<T> s1(p1, d1, a1);
  159. typedef boost::detail::array_deleter<T2[]>* D2;
  160. p3 = reinterpret_cast<T3*>(list.begin());
  161. p1 = reinterpret_cast<T1*>(p2);
  162. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  163. d2->init_list(p2, p3);
  164. return boost::shared_ptr<T>(s1, p1);
  165. }
  166. #endif
  167. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  168. template<typename T>
  169. inline typename boost::detail::sp_if_array<T>::type
  170. make_shared(std::size_t size,
  171. typename boost::detail::array_base<T>::type&& value) {
  172. typedef typename boost::detail::array_inner<T>::type T1;
  173. typedef typename boost::detail::array_base<T1>::type T2;
  174. T1* p1 = 0;
  175. T2* p2 = 0;
  176. std::size_t n1 = size * boost::detail::array_total<T1>::size;
  177. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  178. boost::detail::array_deleter<T2[]> d1(n1);
  179. boost::shared_ptr<T> s1(p1, d1, a1);
  180. typedef boost::detail::array_deleter<T2[]>* D2;
  181. p1 = reinterpret_cast<T1*>(p2);
  182. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  183. d2->init(p2, boost::detail::sp_forward<T2>(value));
  184. return boost::shared_ptr<T>(s1, p1);
  185. }
  186. template<typename T>
  187. inline typename boost::detail::sp_if_size_array<T>::type
  188. make_shared(typename boost::detail::array_base<T>::type&& value) {
  189. typedef typename boost::detail::array_inner<T>::type T1;
  190. typedef typename boost::detail::array_base<T1>::type T2;
  191. enum {
  192. N = boost::detail::array_total<T>::size
  193. };
  194. T1* p1 = 0;
  195. T2* p2 = 0;
  196. boost::detail::make_array_helper<T2[N]> a1(&p2);
  197. boost::detail::array_deleter<T2[N]> d1;
  198. boost::shared_ptr<T> s1(p1, d1, a1);
  199. typedef boost::detail::array_deleter<T2[N]>* D2;
  200. p1 = reinterpret_cast<T1*>(p2);
  201. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  202. d2->init(p2, boost::detail::sp_forward<T2>(value));
  203. return boost::shared_ptr<T>(s1, p1);
  204. }
  205. #endif
  206. #endif
  207. template<typename T>
  208. inline typename boost::detail::sp_if_array<T>::type
  209. make_shared_noinit(std::size_t size) {
  210. typedef typename boost::detail::array_inner<T>::type T1;
  211. typedef typename boost::detail::array_base<T1>::type T2;
  212. T1* p1 = 0;
  213. T2* p2 = 0;
  214. std::size_t n1 = size * boost::detail::array_total<T1>::size;
  215. boost::detail::make_array_helper<T2[]> a1(n1, &p2);
  216. boost::detail::array_deleter<T2[]> d1(n1);
  217. boost::shared_ptr<T> s1(p1, d1, a1);
  218. typedef boost::detail::array_deleter<T2[]>* D2;
  219. p1 = reinterpret_cast<T1*>(p2);
  220. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  221. d2->noinit(p2);
  222. return boost::shared_ptr<T>(s1, p1);
  223. }
  224. template<typename T>
  225. inline typename boost::detail::sp_if_size_array<T>::type
  226. make_shared_noinit() {
  227. typedef typename boost::detail::array_inner<T>::type T1;
  228. typedef typename boost::detail::array_base<T1>::type T2;
  229. enum {
  230. N = boost::detail::array_total<T>::size
  231. };
  232. T1* p1 = 0;
  233. T2* p2 = 0;
  234. boost::detail::make_array_helper<T2[N]> a1(&p2);
  235. boost::detail::array_deleter<T2[N]> d1;
  236. boost::shared_ptr<T> s1(p1, d1, a1);
  237. typedef boost::detail::array_deleter<T2[N]>* D2;
  238. p1 = reinterpret_cast<T1*>(p2);
  239. D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
  240. d2->noinit(p2);
  241. return boost::shared_ptr<T>(s1, p1);
  242. }
  243. }
  244. #endif