varray_detail.hpp 20 KB

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