varray_detail.hpp 22 KB

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