varray_util.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Boost.Container
  2. //
  3. // varray details
  4. //
  5. // Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
  6. // Copyright (c) 2011-2013 Andrew Hundt.
  7. //
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #ifndef BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
  12. #define BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
  13. #include <cstddef>
  14. #include <cstring>
  15. #include <memory>
  16. #include <limits>
  17. #include <boost/config.hpp>
  18. #include <boost/core/no_exceptions_support.hpp>
  19. #include <boost/container/detail/addressof.hpp>
  20. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  21. #include <boost/move/detail/fwd_macros.hpp>
  22. #endif
  23. #include <boost/container/detail/iterator.hpp>
  24. #include <boost/container/detail/mpl.hpp>
  25. #include <boost/container/detail/type_traits.hpp>
  26. #include <boost/move/algorithm.hpp>
  27. #include <boost/move/traits.hpp>
  28. #include <boost/move/utility_core.hpp>
  29. // TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
  30. #if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
  31. #include <vector>
  32. #include <boost/container/vector.hpp>
  33. #endif // BOOST_CONTAINER_VARRAY_ENABLE_ITERATORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
  34. namespace boost { namespace container { namespace varray_detail {
  35. namespace bcd = ::boost::container::dtl;
  36. template <typename I>
  37. struct are_elements_contiguous : boost::container::dtl::is_pointer<I>
  38. {};
  39. #if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
  40. template <typename Pointer>
  41. struct are_elements_contiguous<
  42. bcd::vector_const_iterator<Pointer>
  43. > : bcd::true_type
  44. {};
  45. template <typename Pointer>
  46. struct are_elements_contiguous<
  47. bcd::vector_iterator<Pointer>
  48. > : bcd::true_type
  49. {};
  50. #if defined(BOOST_DINKUMWARE_STDLIB)
  51. template <typename T>
  52. struct are_elements_contiguous<
  53. std::_Vector_const_iterator<T>
  54. > : bcd::true_type
  55. {};
  56. template <typename T>
  57. struct are_elements_contiguous<
  58. std::_Vector_iterator<T>
  59. > : bcd::true_type
  60. {};
  61. #elif defined(BOOST_GNU_STDLIB)
  62. template <typename P, typename T, typename Allocator>
  63. struct are_elements_contiguous<
  64. __gnu_cxx::__normal_iterator<P, std::vector<T, Allocator> >
  65. > : bcd::true_type
  66. {};
  67. #elif defined(_LIBCPP_VERSION)
  68. // TODO - test it first
  69. //template <typename P>
  70. //struct are_elements_contiguous<
  71. // __wrap_iter<P>
  72. //> : bcd::true_type
  73. //{};
  74. #else // OTHER_STDLIB
  75. // TODO - add other iterators implementations
  76. #endif // STDLIB
  77. #endif // BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
  78. template <typename I, typename O>
  79. struct are_corresponding :
  80. bcd::bool_<
  81. bcd::is_same<
  82. bcd::remove_const<
  83. typename ::boost::container::iterator_traits<I>::value_type
  84. >,
  85. bcd::remove_const<
  86. typename ::boost::container::iterator_traits<O>::value_type
  87. >
  88. >::value &&
  89. are_elements_contiguous<I>::value &&
  90. are_elements_contiguous<O>::value
  91. >
  92. {};
  93. template <typename I, typename V>
  94. struct is_corresponding_value :
  95. bcd::bool_<
  96. bcd::is_same<
  97. bcd::remove_const<typename ::boost::container::iterator_traits<I>::value_type>,
  98. bcd::remove_const<V>
  99. >::value
  100. >
  101. {};
  102. // destroy(I, I)
  103. template <typename I>
  104. void destroy_dispatch(I /*first*/, I /*last*/, bcd::true_type const& /*is_trivially_destructible*/)
  105. {}
  106. template <typename I>
  107. void destroy_dispatch(I first, I last, bcd::false_type const& /*is_trivially_destructible*/)
  108. {
  109. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  110. for ( ; first != last ; ++first )
  111. first->~value_type();
  112. }
  113. template <typename I>
  114. void destroy(I first, I last)
  115. {
  116. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  117. destroy_dispatch(first, last, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
  118. }
  119. // destroy(I)
  120. template <typename I>
  121. void destroy_dispatch(I /*pos*/,
  122. bcd::true_type const& /*is_trivially_destructible*/)
  123. {}
  124. template <typename I>
  125. void destroy_dispatch(I pos,
  126. bcd::false_type const& /*is_trivially_destructible*/)
  127. {
  128. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  129. pos->~value_type();
  130. }
  131. template <typename I>
  132. void destroy(I pos)
  133. {
  134. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  135. destroy_dispatch(pos, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
  136. }
  137. // copy(I, I, O)
  138. template <typename I, typename O>
  139. inline O copy_dispatch(I first, I last, O dst, bcd::true_type const& /*use_memmove*/)
  140. {
  141. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  142. const std::size_t d = boost::container::iterator_distance(first, last);
  143. ::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
  144. return dst + d;
  145. }
  146. template <typename I, typename O>
  147. inline O copy_dispatch(I first, I last, O dst, bcd::false_type const& /*use_memmove*/)
  148. {
  149. return std::copy(first, last, dst); // may throw
  150. }
  151. template <typename I, typename O>
  152. inline O copy(I first, I last, O dst)
  153. {
  154. typedef bcd::bool_
  155. < are_corresponding<I, O>::value &&
  156. bcd::is_trivially_copy_assignable<typename ::boost::container::iterator_traits<O>::value_type>::value
  157. > use_memmove;
  158. return copy_dispatch(first, last, dst, use_memmove()); // may throw
  159. }
  160. // uninitialized_copy(I, I, O)
  161. template <typename I, typename O>
  162. inline
  163. O uninitialized_copy_dispatch(I first, I last, O dst,
  164. bcd::true_type const& /*use_memcpy*/)
  165. {
  166. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  167. const std::size_t d = boost::container::iterator_distance(first, last);
  168. ::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
  169. return dst + d;
  170. }
  171. template <typename I, typename F>
  172. inline
  173. F uninitialized_copy_dispatch(I first, I last, F dst,
  174. bcd::false_type const& /*use_memcpy*/)
  175. {
  176. return std::uninitialized_copy(first, last, dst); // may throw
  177. }
  178. template <typename I, typename F>
  179. inline
  180. F uninitialized_copy(I first, I last, F dst)
  181. {
  182. typedef bcd::bool_
  183. < are_corresponding<I, F>::value &&
  184. bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<F>::value_type>::value
  185. > use_memcpy;
  186. return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
  187. }
  188. // uninitialized_move(I, I, O)
  189. template <typename I, typename O>
  190. inline
  191. O uninitialized_move_dispatch(I first, I last, O dst,
  192. bcd::true_type const& /*use_memcpy*/)
  193. {
  194. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  195. const std::size_t d = boost::container::iterator_distance(first, last);
  196. ::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
  197. return dst + d;
  198. }
  199. template <typename I, typename O>
  200. inline
  201. O uninitialized_move_dispatch(I first, I last, O dst,
  202. bcd::false_type const& /*use_memcpy*/)
  203. {
  204. //return boost::uninitialized_move(first, last, dst); // may throw
  205. O o = dst;
  206. BOOST_TRY
  207. {
  208. typedef typename boost::container::iterator_traits<O>::value_type value_type;
  209. for (; first != last; ++first, ++o )
  210. new (boost::container::dtl::addressof(*o)) value_type(boost::move(*first));
  211. }
  212. BOOST_CATCH(...)
  213. {
  214. destroy(dst, o);
  215. BOOST_RETHROW;
  216. }
  217. BOOST_CATCH_END
  218. return dst;
  219. }
  220. template <typename I, typename O>
  221. inline
  222. O uninitialized_move(I first, I last, O dst)
  223. {
  224. typedef bcd::bool_
  225. < are_corresponding<I, O>::value &&
  226. bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
  227. > use_memcpy;
  228. return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
  229. }
  230. // TODO - move uses memmove - implement 2nd version using memcpy?
  231. // move(I, I, O)
  232. template <typename I, typename O>
  233. inline
  234. O move_dispatch(I first, I last, O dst,
  235. bcd::true_type const& /*use_memmove*/)
  236. {
  237. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  238. const std::size_t d = boost::container::iterator_distance(first, last);
  239. ::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type)*d );
  240. return dst + d;
  241. }
  242. template <typename I, typename O>
  243. inline
  244. O move_dispatch(I first, I last, O dst,
  245. bcd::false_type const& /*use_memmove*/)
  246. {
  247. return boost::move(first, last, dst); // may throw
  248. }
  249. template <typename I, typename O>
  250. inline
  251. O move(I first, I last, O dst)
  252. {
  253. typedef bcd::bool_
  254. < are_corresponding<I, O>::value &&
  255. bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
  256. > use_memmove;
  257. return move_dispatch(first, last, dst, use_memmove()); // may throw
  258. }
  259. // move_backward(BDI, BDI, BDO)
  260. template <typename BDI, typename BDO>
  261. inline
  262. BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
  263. bcd::true_type const& /*use_memmove*/)
  264. {
  265. typedef typename ::boost::container::iterator_traits<BDI>::value_type value_type;
  266. const std::size_t d = boost::container::iterator_distance(first, last);
  267. BDO foo(dst - d);
  268. ::memmove(boost::container::dtl::addressof(*foo), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
  269. return foo;
  270. }
  271. template <typename BDI, typename BDO>
  272. inline
  273. BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
  274. bcd::false_type const& /*use_memmove*/)
  275. {
  276. return boost::move_backward(first, last, dst); // may throw
  277. }
  278. template <typename BDI, typename BDO>
  279. inline
  280. BDO move_backward(BDI first, BDI last, BDO dst)
  281. {
  282. typedef bcd::bool_
  283. < are_corresponding<BDI, BDO>::value &&
  284. bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<BDO>::value_type>::value
  285. > use_memmove;
  286. return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
  287. }
  288. template <typename T>
  289. struct has_nothrow_move : public
  290. bcd::bool_<
  291. ::boost::has_nothrow_move<
  292. typename bcd::remove_const<T>::type
  293. >::value
  294. ||
  295. ::boost::has_nothrow_move<T>::value
  296. >
  297. {};
  298. // uninitialized_move_if_noexcept(I, I, O)
  299. template <typename I, typename O>
  300. inline
  301. O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
  302. { return uninitialized_move(first, last, dst); }
  303. template <typename I, typename O>
  304. inline
  305. O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
  306. { return uninitialized_copy(first, last, dst); }
  307. template <typename I, typename O>
  308. inline
  309. O uninitialized_move_if_noexcept(I first, I last, O dst)
  310. {
  311. typedef has_nothrow_move<
  312. typename ::boost::container::iterator_traits<O>::value_type
  313. > use_move;
  314. return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
  315. }
  316. // move_if_noexcept(I, I, O)
  317. template <typename I, typename O>
  318. inline
  319. O move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
  320. { return move(first, last, dst); }
  321. template <typename I, typename O>
  322. inline
  323. O move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
  324. { return copy(first, last, dst); }
  325. template <typename I, typename O>
  326. inline
  327. O move_if_noexcept(I first, I last, O dst)
  328. {
  329. typedef has_nothrow_move<
  330. typename ::boost::container::iterator_traits<O>::value_type
  331. > use_move;
  332. return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
  333. }
  334. // uninitialized_fill(I, I)
  335. template <typename I>
  336. inline
  337. void uninitialized_fill_dispatch(I , I ,
  338. bcd::true_type const& /*is_trivially_default_constructible*/,
  339. bcd::true_type const& /*disable_trivial_init*/)
  340. {}
  341. template <typename I>
  342. inline
  343. void uninitialized_fill_dispatch(I first, I last,
  344. bcd::true_type const& /*is_trivially_default_constructible*/,
  345. bcd::false_type const& /*disable_trivial_init*/)
  346. {
  347. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  348. for ( ; first != last ; ++first )
  349. new (boost::container::dtl::addressof(*first)) value_type();
  350. }
  351. template <typename I, typename DisableTrivialInit>
  352. inline
  353. void uninitialized_fill_dispatch(I first, I last,
  354. bcd::false_type const& /*is_trivially_default_constructible*/,
  355. DisableTrivialInit const& /*not_used*/)
  356. {
  357. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  358. I it = first;
  359. BOOST_TRY
  360. {
  361. for ( ; it != last ; ++it )
  362. new (boost::container::dtl::addressof(*it)) value_type(); // may throw
  363. }
  364. BOOST_CATCH(...)
  365. {
  366. destroy(first, it);
  367. BOOST_RETHROW;
  368. }
  369. BOOST_CATCH_END
  370. }
  371. template <typename I, typename DisableTrivialInit>
  372. inline
  373. void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
  374. {
  375. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  376. uninitialized_fill_dispatch(first, last
  377. , bcd::bool_<bcd::is_trivially_default_constructible<value_type>::value>()
  378. , disable_trivial_init); // may throw
  379. }
  380. // construct(I)
  381. template <typename I>
  382. inline
  383. void construct_dispatch(bcd::true_type const& /*dont_init*/, I /*pos*/)
  384. {}
  385. template <typename I>
  386. inline
  387. void construct_dispatch(bcd::false_type const& /*dont_init*/, I pos)
  388. {
  389. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  390. new (static_cast<void*>(::boost::container::dtl::addressof(*pos))) value_type(); // may throw
  391. }
  392. template <typename DisableTrivialInit, typename I>
  393. inline
  394. void construct(DisableTrivialInit const&, I pos)
  395. {
  396. typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
  397. bcd::bool_<
  398. bcd::is_trivially_default_constructible<value_type>::value &&
  399. DisableTrivialInit::value
  400. > dont_init;
  401. construct_dispatch(dont_init(), pos); // may throw
  402. }
  403. // construct(I, V)
  404. template <typename I, typename V>
  405. inline
  406. void construct_dispatch(I pos, V const& v, bcd::true_type const& /*use_memcpy*/)
  407. {
  408. ::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
  409. }
  410. template <typename I, typename P>
  411. inline
  412. void construct_dispatch(I pos, P const& p,
  413. bcd::false_type const& /*use_memcpy*/)
  414. {
  415. typedef typename ::boost::container::iterator_traits<I>::value_type V;
  416. new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(p); // may throw
  417. }
  418. template <typename DisableTrivialInit, typename I, typename P>
  419. inline
  420. void construct(DisableTrivialInit const&, I pos, P const& p)
  421. {
  422. typedef bcd::bool_
  423. < is_corresponding_value<I, P>::value &&
  424. bcd::is_trivially_copy_constructible<P>::value
  425. > use_memcpy;
  426. construct_dispatch(pos, p, use_memcpy()); // may throw
  427. }
  428. // Needed by push_back(V &&)
  429. template <typename DisableTrivialInit, typename I, typename P>
  430. inline
  431. void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
  432. {
  433. typedef typename ::boost::container::iterator_traits<I>::value_type V;
  434. new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::move(p)); // may throw
  435. }
  436. // Needed by emplace_back() and emplace()
  437. #if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
  438. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  439. template <typename DisableTrivialInit, typename I, class ...Args>
  440. inline
  441. void construct(DisableTrivialInit const&,
  442. I pos,
  443. BOOST_FWD_REF(Args) ...args)
  444. {
  445. typedef typename ::boost::container::iterator_traits<I>::value_type V;
  446. new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
  447. }
  448. #else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
  449. // BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0
  450. // !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
  451. // which means that version with one parameter may take V const& v
  452. #define BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE(N) \
  453. template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  454. inline void construct(DisableTrivialInit const&, I pos, BOOST_FWD_REF(P) p BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
  455. {\
  456. typedef typename ::boost::container::iterator_traits<I>::value_type V;\
  457. new (static_cast<void*>(boost::container::dtl::addressof(*pos)))\
  458. V(::boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/\
  459. }
  460. BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE)
  461. #undef BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE
  462. #endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
  463. #endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
  464. // assign(I, V)
  465. template <typename I, typename V>
  466. inline
  467. void assign_dispatch(I pos, V const& v,
  468. bcd::true_type const& /*use_memcpy*/)
  469. {
  470. ::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
  471. }
  472. template <typename I, typename V>
  473. inline
  474. void assign_dispatch(I pos, V const& v,
  475. bcd::false_type const& /*use_memcpy*/)
  476. {
  477. *pos = v; // may throw
  478. }
  479. template <typename I, typename V>
  480. inline
  481. void assign(I pos, V const& v)
  482. {
  483. typedef bcd::bool_
  484. < is_corresponding_value<I, V>::value &&
  485. bcd::is_trivially_copy_assignable<V>::value
  486. > use_memcpy;
  487. assign_dispatch(pos, v, use_memcpy()); // may throw
  488. }
  489. template <typename I, typename V>
  490. inline
  491. void assign(I pos, BOOST_RV_REF(V) v)
  492. {
  493. *pos = boost::move(v); // may throw
  494. }
  495. // uninitialized_copy_s
  496. template <typename I, typename F>
  497. inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
  498. {
  499. std::size_t count = 0;
  500. F it = dest;
  501. BOOST_TRY
  502. {
  503. for ( ; first != last ; ++it, ++first, ++count )
  504. {
  505. if ( max_count <= count )
  506. return (std::numeric_limits<std::size_t>::max)();
  507. // dummy 0 as DisableTrivialInit
  508. construct(0, it, *first); // may throw
  509. }
  510. }
  511. BOOST_CATCH(...)
  512. {
  513. destroy(dest, it);
  514. BOOST_RETHROW;
  515. }
  516. BOOST_CATCH_END
  517. return count;
  518. }
  519. // scoped_destructor
  520. template<class T>
  521. class scoped_destructor
  522. {
  523. public:
  524. scoped_destructor(T * ptr) : m_ptr(ptr) {}
  525. ~scoped_destructor()
  526. {
  527. if(m_ptr)
  528. destroy(m_ptr);
  529. }
  530. void release() { m_ptr = 0; }
  531. private:
  532. T * m_ptr;
  533. };
  534. }}} // namespace boost::container::varray_detail
  535. #endif // BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP