copy_move_algo.hpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
  11. #define BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #if defined(BOOST_HAS_PRAGMA_ONCE)
  16. # pragma once
  17. #endif
  18. // container
  19. #include <boost/container/allocator_traits.hpp>
  20. // container/detail
  21. #include <boost/container/detail/iterator.hpp>
  22. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  23. #include <boost/container/detail/mpl.hpp>
  24. #include <boost/container/detail/type_traits.hpp>
  25. #include <boost/container/detail/construct_in_place.hpp>
  26. // move
  27. #include <boost/move/adl_move_swap.hpp>
  28. #include <boost/move/iterator.hpp>
  29. #include <boost/move/utility_core.hpp>
  30. // other
  31. #include <boost/core/no_exceptions_support.hpp>
  32. // std
  33. #include <cstring> //for memmove/memcpy
  34. #if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
  35. #pragma GCC diagnostic push
  36. #pragma GCC diagnostic ignored "-Wclass-memaccess"
  37. #endif
  38. namespace boost {
  39. namespace container {
  40. namespace dtl {
  41. template<class I>
  42. struct are_elements_contiguous
  43. {
  44. static const bool value = false;
  45. };
  46. /////////////////////////
  47. // raw pointers
  48. /////////////////////////
  49. template<class T>
  50. struct are_elements_contiguous<T*>
  51. {
  52. static const bool value = true;
  53. };
  54. /////////////////////////
  55. // move iterators
  56. /////////////////////////
  57. template<class It>
  58. struct are_elements_contiguous< ::boost::move_iterator<It> >
  59. : are_elements_contiguous<It>
  60. {};
  61. } //namespace dtl {
  62. /////////////////////////
  63. // predeclarations
  64. /////////////////////////
  65. template <class Pointer, bool IsConst>
  66. class vec_iterator;
  67. } //namespace container {
  68. namespace interprocess {
  69. template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
  70. class offset_ptr;
  71. } //namespace interprocess {
  72. namespace container {
  73. namespace dtl {
  74. /////////////////////////
  75. //vector_[const_]iterator
  76. /////////////////////////
  77. template <class Pointer, bool IsConst>
  78. struct are_elements_contiguous<boost::container::vec_iterator<Pointer, IsConst> >
  79. {
  80. static const bool value = true;
  81. };
  82. /////////////////////////
  83. // offset_ptr
  84. /////////////////////////
  85. template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
  86. struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
  87. {
  88. static const bool value = true;
  89. };
  90. template <typename I, typename O>
  91. struct are_contiguous_and_same
  92. : boost::move_detail::and_
  93. < are_elements_contiguous<I>
  94. , are_elements_contiguous<O>
  95. , is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
  96. , typename ::boost::container::iterator_traits<O>::value_type
  97. >
  98. >
  99. {};
  100. template <typename I, typename O>
  101. struct is_memtransfer_copy_assignable
  102. : boost::move_detail::and_
  103. < are_contiguous_and_same<I, O>
  104. , dtl::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >
  105. >
  106. {};
  107. template <typename I, typename O>
  108. struct is_memtransfer_copy_constructible
  109. : boost::move_detail::and_
  110. < are_contiguous_and_same<I, O>
  111. , dtl::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >
  112. >
  113. {};
  114. template <typename I, typename O, typename R>
  115. struct enable_if_memtransfer_copy_constructible
  116. : enable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
  117. {};
  118. template <typename I, typename O, typename R>
  119. struct disable_if_memtransfer_copy_constructible
  120. : disable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
  121. {};
  122. template <typename I, typename O, typename R>
  123. struct enable_if_memtransfer_copy_assignable
  124. : enable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
  125. {};
  126. template <typename I, typename O, typename R>
  127. struct disable_if_memtransfer_copy_assignable
  128. : disable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
  129. {};
  130. template
  131. <typename I, // I models InputIterator
  132. typename F> // F models ForwardIterator
  133. inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  134. {
  135. typedef typename boost::container::iterator_traits<I>::value_type value_type;
  136. typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
  137. if(n){
  138. std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
  139. boost::container::iterator_advance(r, n);
  140. }
  141. return r;
  142. }
  143. template
  144. <typename I, // I models InputIterator
  145. typename U, // U models unsigned integral constant
  146. typename F> // F models ForwardIterator
  147. F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  148. {
  149. typedef typename boost::container::iterator_traits<I>::value_type value_type;
  150. if(n){
  151. std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
  152. boost::container::iterator_advance(r, n);
  153. }
  154. return r;
  155. }
  156. template
  157. <typename I, // I models InputIterator
  158. typename U, // U models unsigned integral constant
  159. typename F> // F models ForwardIterator
  160. I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  161. {
  162. if(n){
  163. typedef typename boost::container::iterator_traits<I>::value_type value_type;
  164. std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
  165. boost::container::iterator_advance(f, n);
  166. }
  167. return f;
  168. }
  169. template
  170. <typename I, // I models InputIterator
  171. typename U, // U models unsigned integral constant
  172. typename F> // F models ForwardIterator
  173. I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
  174. {
  175. typedef typename boost::container::iterator_traits<I>::value_type value_type;
  176. if(n){
  177. std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
  178. boost::container::iterator_advance(f, n);
  179. boost::container::iterator_advance(r, n);
  180. }
  181. return f;
  182. }
  183. template <typename O>
  184. struct is_memzero_initializable
  185. {
  186. typedef typename ::boost::container::iterator_traits<O>::value_type value_type;
  187. static const bool value = are_elements_contiguous<O>::value &&
  188. ( dtl::is_integral<value_type>::value || dtl::is_enum<value_type>::value
  189. #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
  190. || dtl::is_pointer<value_type>::value
  191. #endif
  192. #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
  193. || dtl::is_floating_point<value_type>::value
  194. #endif
  195. #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
  196. || dtl::is_pod<value_type>::value
  197. #endif
  198. );
  199. };
  200. template <typename O, typename R>
  201. struct enable_if_memzero_initializable
  202. : enable_if_c<dtl::is_memzero_initializable<O>::value, R>
  203. {};
  204. template <typename O, typename R>
  205. struct disable_if_memzero_initializable
  206. : enable_if_c<!dtl::is_memzero_initializable<O>::value, R>
  207. {};
  208. template <typename I, typename R>
  209. struct enable_if_trivially_destructible
  210. : enable_if_c < dtl::is_trivially_destructible
  211. <typename boost::container::iterator_traits<I>::value_type>::value
  212. , R>
  213. {};
  214. template <typename I, typename R>
  215. struct disable_if_trivially_destructible
  216. : enable_if_c <!dtl::is_trivially_destructible
  217. <typename boost::container::iterator_traits<I>::value_type>::value
  218. , R>
  219. {};
  220. } //namespace dtl {
  221. //////////////////////////////////////////////////////////////////////////////
  222. //
  223. // uninitialized_move_alloc
  224. //
  225. //////////////////////////////////////////////////////////////////////////////
  226. //! <b>Effects</b>:
  227. //! \code
  228. //! for (; f != l; ++r, ++f)
  229. //! allocator_traits::construct(a, &*r, boost::move(*f));
  230. //! \endcode
  231. //!
  232. //! <b>Returns</b>: r
  233. template
  234. <typename Allocator,
  235. typename I, // I models InputIterator
  236. typename F> // F models ForwardIterator
  237. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
  238. uninitialized_move_alloc(Allocator &a, I f, I l, F r)
  239. {
  240. F back = r;
  241. BOOST_TRY{
  242. while (f != l) {
  243. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
  244. ++f; ++r;
  245. }
  246. }
  247. BOOST_CATCH(...){
  248. for (; back != r; ++back){
  249. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  250. }
  251. BOOST_RETHROW;
  252. }
  253. BOOST_CATCH_END
  254. return r;
  255. }
  256. template
  257. <typename Allocator,
  258. typename I, // I models InputIterator
  259. typename F> // F models ForwardIterator
  260. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
  261. uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  262. { return dtl::memmove(f, l, r); }
  263. //////////////////////////////////////////////////////////////////////////////
  264. //
  265. // uninitialized_move_alloc_n
  266. //
  267. //////////////////////////////////////////////////////////////////////////////
  268. //! <b>Effects</b>:
  269. //! \code
  270. //! for (; n--; ++r, ++f)
  271. //! allocator_traits::construct(a, &*r, boost::move(*f));
  272. //! \endcode
  273. //!
  274. //! <b>Returns</b>: r
  275. template
  276. <typename Allocator,
  277. typename I, // I models InputIterator
  278. typename F> // F models ForwardIterator
  279. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
  280. uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  281. {
  282. F back = r;
  283. BOOST_TRY{
  284. while (n--) {
  285. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
  286. ++f; ++r;
  287. }
  288. }
  289. BOOST_CATCH(...){
  290. for (; back != r; ++back){
  291. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  292. }
  293. BOOST_RETHROW;
  294. }
  295. BOOST_CATCH_END
  296. return r;
  297. }
  298. template
  299. <typename Allocator,
  300. typename I, // I models InputIterator
  301. typename F> // F models ForwardIterator
  302. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
  303. uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  304. { return dtl::memmove_n(f, n, r); }
  305. //////////////////////////////////////////////////////////////////////////////
  306. //
  307. // uninitialized_move_alloc_n_source
  308. //
  309. //////////////////////////////////////////////////////////////////////////////
  310. //! <b>Effects</b>:
  311. //! \code
  312. //! for (; n--; ++r, ++f)
  313. //! allocator_traits::construct(a, &*r, boost::move(*f));
  314. //! \endcode
  315. //!
  316. //! <b>Returns</b>: f (after incremented)
  317. template
  318. <typename Allocator,
  319. typename I, // I models InputIterator
  320. typename F> // F models ForwardIterator
  321. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
  322. uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  323. {
  324. F back = r;
  325. BOOST_TRY{
  326. while (n--) {
  327. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
  328. ++f; ++r;
  329. }
  330. }
  331. BOOST_CATCH(...){
  332. for (; back != r; ++back){
  333. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  334. }
  335. BOOST_RETHROW;
  336. }
  337. BOOST_CATCH_END
  338. return f;
  339. }
  340. template
  341. <typename Allocator,
  342. typename I, // I models InputIterator
  343. typename F> // F models ForwardIterator
  344. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
  345. uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  346. { return dtl::memmove_n_source(f, n, r); }
  347. //////////////////////////////////////////////////////////////////////////////
  348. //
  349. // uninitialized_copy_alloc
  350. //
  351. //////////////////////////////////////////////////////////////////////////////
  352. //! <b>Effects</b>:
  353. //! \code
  354. //! for (; f != l; ++r, ++f)
  355. //! allocator_traits::construct(a, &*r, *f);
  356. //! \endcode
  357. //!
  358. //! <b>Returns</b>: r
  359. template
  360. <typename Allocator,
  361. typename I, // I models InputIterator
  362. typename F> // F models ForwardIterator
  363. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
  364. uninitialized_copy_alloc(Allocator &a, I f, I l, F r)
  365. {
  366. F back = r;
  367. BOOST_TRY{
  368. while (f != l) {
  369. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
  370. ++f; ++r;
  371. }
  372. }
  373. BOOST_CATCH(...){
  374. for (; back != r; ++back){
  375. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  376. }
  377. BOOST_RETHROW;
  378. }
  379. BOOST_CATCH_END
  380. return r;
  381. }
  382. template
  383. <typename Allocator,
  384. typename I, // I models InputIterator
  385. typename F> // F models ForwardIterator
  386. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
  387. uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  388. { return dtl::memmove(f, l, r); }
  389. //////////////////////////////////////////////////////////////////////////////
  390. //
  391. // uninitialized_copy_alloc_n
  392. //
  393. //////////////////////////////////////////////////////////////////////////////
  394. //! <b>Effects</b>:
  395. //! \code
  396. //! for (; n--; ++r, ++f)
  397. //! allocator_traits::construct(a, &*r, *f);
  398. //! \endcode
  399. //!
  400. //! <b>Returns</b>: r
  401. template
  402. <typename Allocator,
  403. typename I, // I models InputIterator
  404. typename F> // F models ForwardIterator
  405. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
  406. uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  407. {
  408. F back = r;
  409. BOOST_TRY{
  410. while (n--) {
  411. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
  412. ++f; ++r;
  413. }
  414. }
  415. BOOST_CATCH(...){
  416. for (; back != r; ++back){
  417. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  418. }
  419. BOOST_RETHROW;
  420. }
  421. BOOST_CATCH_END
  422. return r;
  423. }
  424. template
  425. <typename Allocator,
  426. typename I, // I models InputIterator
  427. typename F> // F models ForwardIterator
  428. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
  429. uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  430. { return dtl::memmove_n(f, n, r); }
  431. //////////////////////////////////////////////////////////////////////////////
  432. //
  433. // uninitialized_copy_alloc_n_source
  434. //
  435. //////////////////////////////////////////////////////////////////////////////
  436. //! <b>Effects</b>:
  437. //! \code
  438. //! for (; n--; ++r, ++f)
  439. //! allocator_traits::construct(a, &*r, *f);
  440. //! \endcode
  441. //!
  442. //! <b>Returns</b>: f (after incremented)
  443. template
  444. <typename Allocator,
  445. typename I, // I models InputIterator
  446. typename F> // F models ForwardIterator
  447. inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
  448. uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  449. {
  450. F back = r;
  451. BOOST_TRY{
  452. while (n--) {
  453. boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
  454. ++f; ++r;
  455. }
  456. }
  457. BOOST_CATCH(...){
  458. for (; back != r; ++back){
  459. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  460. }
  461. BOOST_RETHROW;
  462. }
  463. BOOST_CATCH_END
  464. return f;
  465. }
  466. template
  467. <typename Allocator,
  468. typename I, // I models InputIterator
  469. typename F> // F models ForwardIterator
  470. inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
  471. uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  472. { return dtl::memmove_n_source(f, n, r); }
  473. //////////////////////////////////////////////////////////////////////////////
  474. //
  475. // uninitialized_value_init_alloc_n
  476. //
  477. //////////////////////////////////////////////////////////////////////////////
  478. //! <b>Effects</b>:
  479. //! \code
  480. //! for (; n--; ++r, ++f)
  481. //! allocator_traits::construct(a, &*r);
  482. //! \endcode
  483. //!
  484. //! <b>Returns</b>: r
  485. template
  486. <typename Allocator,
  487. typename F> // F models ForwardIterator
  488. inline typename dtl::disable_if_memzero_initializable<F, F>::type
  489. uninitialized_value_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  490. {
  491. F back = r;
  492. BOOST_TRY{
  493. while (n--) {
  494. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r));
  495. ++r;
  496. }
  497. }
  498. BOOST_CATCH(...){
  499. for (; back != r; ++back){
  500. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  501. }
  502. BOOST_RETHROW;
  503. }
  504. BOOST_CATCH_END
  505. return r;
  506. }
  507. template
  508. <typename Allocator,
  509. typename F> // F models ForwardIterator
  510. inline typename dtl::enable_if_memzero_initializable<F, F>::type
  511. uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  512. {
  513. typedef typename boost::container::iterator_traits<F>::value_type value_type;
  514. std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
  515. boost::container::iterator_advance(r, n);
  516. return r;
  517. }
  518. //////////////////////////////////////////////////////////////////////////////
  519. //
  520. // uninitialized_default_init_alloc_n
  521. //
  522. //////////////////////////////////////////////////////////////////////////////
  523. //! <b>Effects</b>:
  524. //! \code
  525. //! for (; n--; ++r, ++f)
  526. //! allocator_traits::construct(a, &*r);
  527. //! \endcode
  528. //!
  529. //! <b>Returns</b>: r
  530. template
  531. <typename Allocator,
  532. typename F> // F models ForwardIterator
  533. inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  534. {
  535. F back = r;
  536. BOOST_TRY{
  537. while (n--) {
  538. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init);
  539. ++r;
  540. }
  541. }
  542. BOOST_CATCH(...){
  543. for (; back != r; ++back){
  544. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  545. }
  546. BOOST_RETHROW;
  547. }
  548. BOOST_CATCH_END
  549. return r;
  550. }
  551. //////////////////////////////////////////////////////////////////////////////
  552. //
  553. // uninitialized_fill_alloc
  554. //
  555. //////////////////////////////////////////////////////////////////////////////
  556. //! <b>Effects</b>:
  557. //! \code
  558. //! for (; f != l; ++r, ++f)
  559. //! allocator_traits::construct(a, &*r, *f);
  560. //! \endcode
  561. //!
  562. //! <b>Returns</b>: r
  563. template
  564. <typename Allocator,
  565. typename F, // F models ForwardIterator
  566. typename T>
  567. inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t)
  568. {
  569. F back = f;
  570. BOOST_TRY{
  571. while (f != l) {
  572. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t);
  573. ++f;
  574. }
  575. }
  576. BOOST_CATCH(...){
  577. for (; back != l; ++back){
  578. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  579. }
  580. BOOST_RETHROW;
  581. }
  582. BOOST_CATCH_END
  583. }
  584. //////////////////////////////////////////////////////////////////////////////
  585. //
  586. // uninitialized_fill_alloc_n
  587. //
  588. //////////////////////////////////////////////////////////////////////////////
  589. //! <b>Effects</b>:
  590. //! \code
  591. //! for (; n--; ++r, ++f)
  592. //! allocator_traits::construct(a, &*r, v);
  593. //! \endcode
  594. //!
  595. //! <b>Returns</b>: r
  596. template
  597. <typename Allocator,
  598. typename T,
  599. typename F> // F models ForwardIterator
  600. inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
  601. {
  602. F back = r;
  603. BOOST_TRY{
  604. while (n--) {
  605. allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v);
  606. ++r;
  607. }
  608. }
  609. BOOST_CATCH(...){
  610. for (; back != r; ++back){
  611. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
  612. }
  613. BOOST_RETHROW;
  614. }
  615. BOOST_CATCH_END
  616. return r;
  617. }
  618. //////////////////////////////////////////////////////////////////////////////
  619. //
  620. // copy
  621. //
  622. //////////////////////////////////////////////////////////////////////////////
  623. template
  624. <typename I, // I models InputIterator
  625. typename F> // F models ForwardIterator
  626. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
  627. copy(I f, I l, F r)
  628. {
  629. while (f != l) {
  630. *r = *f;
  631. ++f; ++r;
  632. }
  633. return r;
  634. }
  635. template
  636. <typename I, // I models InputIterator
  637. typename F> // F models ForwardIterator
  638. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
  639. copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  640. { return dtl::memmove(f, l, r); }
  641. //////////////////////////////////////////////////////////////////////////////
  642. //
  643. // copy_n
  644. //
  645. //////////////////////////////////////////////////////////////////////////////
  646. template
  647. <typename I, // I models InputIterator
  648. typename U, // U models unsigned integral constant
  649. typename F> // F models ForwardIterator
  650. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
  651. copy_n(I f, U n, F r)
  652. {
  653. while (n--) {
  654. *r = *f;
  655. ++f; ++r;
  656. }
  657. return r;
  658. }
  659. template
  660. <typename I, // I models InputIterator
  661. typename U, // U models unsigned integral constant
  662. typename F> // F models ForwardIterator
  663. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
  664. copy_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  665. { return dtl::memmove_n(f, n, r); }
  666. //////////////////////////////////////////////////////////////////////////////
  667. //
  668. // copy_n_source
  669. //
  670. //////////////////////////////////////////////////////////////////////////////
  671. template
  672. <typename I, // I models InputIterator
  673. typename U, // U models unsigned integral constant
  674. typename F> // F models ForwardIterator
  675. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
  676. copy_n_source(I f, U n, F r)
  677. {
  678. while (n--) {
  679. boost::container::assign_in_place(r, f);
  680. ++f; ++r;
  681. }
  682. return f;
  683. }
  684. template
  685. <typename I, // I models InputIterator
  686. typename U, // U models unsigned integral constant
  687. typename F> // F models ForwardIterator
  688. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
  689. copy_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  690. { return dtl::memmove_n_source(f, n, r); }
  691. //////////////////////////////////////////////////////////////////////////////
  692. //
  693. // copy_n_source_dest
  694. //
  695. //////////////////////////////////////////////////////////////////////////////
  696. template
  697. <typename I, // I models InputIterator
  698. typename U, // U models unsigned integral constant
  699. typename F> // F models ForwardIterator
  700. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
  701. copy_n_source_dest(I f, U n, F &r)
  702. {
  703. while (n--) {
  704. *r = *f;
  705. ++f; ++r;
  706. }
  707. return f;
  708. }
  709. template
  710. <typename I, // I models InputIterator
  711. typename U, // U models unsigned integral constant
  712. typename F> // F models ForwardIterator
  713. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
  714. copy_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
  715. { return dtl::memmove_n_source_dest(f, n, r); }
  716. //////////////////////////////////////////////////////////////////////////////
  717. //
  718. // move
  719. //
  720. //////////////////////////////////////////////////////////////////////////////
  721. template
  722. <typename I, // I models InputIterator
  723. typename F> // F models ForwardIterator
  724. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
  725. move(I f, I l, F r)
  726. {
  727. while (f != l) {
  728. *r = ::boost::move(*f);
  729. ++f; ++r;
  730. }
  731. return r;
  732. }
  733. template
  734. <typename I, // I models InputIterator
  735. typename F> // F models ForwardIterator
  736. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
  737. move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  738. { return dtl::memmove(f, l, r); }
  739. //////////////////////////////////////////////////////////////////////////////
  740. //
  741. // move_n
  742. //
  743. //////////////////////////////////////////////////////////////////////////////
  744. template
  745. <typename I, // I models InputIterator
  746. typename U, // U models unsigned integral constant
  747. typename F> // F models ForwardIterator
  748. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
  749. move_n(I f, U n, F r)
  750. {
  751. while (n--) {
  752. *r = ::boost::move(*f);
  753. ++f; ++r;
  754. }
  755. return r;
  756. }
  757. template
  758. <typename I, // I models InputIterator
  759. typename U, // U models unsigned integral constant
  760. typename F> // F models ForwardIterator
  761. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
  762. move_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  763. { return dtl::memmove_n(f, n, r); }
  764. //////////////////////////////////////////////////////////////////////////////
  765. //
  766. // move_backward
  767. //
  768. //////////////////////////////////////////////////////////////////////////////
  769. template
  770. <typename I, // I models BidirectionalIterator
  771. typename F> // F models ForwardIterator
  772. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
  773. move_backward(I f, I l, F r)
  774. {
  775. while (f != l) {
  776. --l; --r;
  777. *r = ::boost::move(*l);
  778. }
  779. return r;
  780. }
  781. template
  782. <typename I, // I models InputIterator
  783. typename F> // F models ForwardIterator
  784. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
  785. move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
  786. {
  787. typedef typename boost::container::iterator_traits<I>::value_type value_type;
  788. const typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
  789. r -= n;
  790. std::memmove((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
  791. return r;
  792. }
  793. //////////////////////////////////////////////////////////////////////////////
  794. //
  795. // move_n_source_dest
  796. //
  797. //////////////////////////////////////////////////////////////////////////////
  798. template
  799. <typename I // I models InputIterator
  800. ,typename U // U models unsigned integral constant
  801. ,typename F> // F models ForwardIterator
  802. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
  803. move_n_source_dest(I f, U n, F &r)
  804. {
  805. while (n--) {
  806. *r = ::boost::move(*f);
  807. ++f; ++r;
  808. }
  809. return f;
  810. }
  811. template
  812. <typename I // I models InputIterator
  813. ,typename U // U models unsigned integral constant
  814. ,typename F> // F models ForwardIterator
  815. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
  816. move_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
  817. { return dtl::memmove_n_source_dest(f, n, r); }
  818. //////////////////////////////////////////////////////////////////////////////
  819. //
  820. // move_n_source
  821. //
  822. //////////////////////////////////////////////////////////////////////////////
  823. template
  824. <typename I // I models InputIterator
  825. ,typename U // U models unsigned integral constant
  826. ,typename F> // F models ForwardIterator
  827. inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
  828. move_n_source(I f, U n, F r)
  829. {
  830. while (n--) {
  831. *r = ::boost::move(*f);
  832. ++f; ++r;
  833. }
  834. return f;
  835. }
  836. template
  837. <typename I // I models InputIterator
  838. ,typename U // U models unsigned integral constant
  839. ,typename F> // F models ForwardIterator
  840. inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
  841. move_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
  842. { return dtl::memmove_n_source(f, n, r); }
  843. //////////////////////////////////////////////////////////////////////////////
  844. //
  845. // destroy_alloc_n
  846. //
  847. //////////////////////////////////////////////////////////////////////////////
  848. template
  849. <typename Allocator
  850. ,typename I // I models InputIterator
  851. ,typename U> // U models unsigned integral constant
  852. inline typename dtl::disable_if_trivially_destructible<I, void>::type
  853. destroy_alloc_n(Allocator &a, I f, U n)
  854. {
  855. while(n){
  856. --n;
  857. allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
  858. ++f;
  859. }
  860. }
  861. template
  862. <typename Allocator
  863. ,typename I // I models InputIterator
  864. ,typename U> // U models unsigned integral constant
  865. inline typename dtl::enable_if_trivially_destructible<I, void>::type
  866. destroy_alloc_n(Allocator &, I, U)
  867. {}
  868. //////////////////////////////////////////////////////////////////////////////
  869. //
  870. // deep_swap_alloc_n
  871. //
  872. //////////////////////////////////////////////////////////////////////////////
  873. template
  874. <std::size_t MaxTmpBytes
  875. ,typename Allocator
  876. ,typename F // F models ForwardIterator
  877. ,typename G // G models ForwardIterator
  878. >
  879. inline typename dtl::disable_if_memtransfer_copy_assignable<F, G, void>::type
  880. deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
  881. , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
  882. {
  883. typename allocator_traits<Allocator>::size_type n = 0;
  884. for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
  885. boost::adl_move_swap(*short_range_f, *large_range_f);
  886. }
  887. boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
  888. boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
  889. }
  890. static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
  891. template
  892. <std::size_t MaxTmpBytes
  893. ,typename Allocator
  894. ,typename F // F models ForwardIterator
  895. ,typename G // G models ForwardIterator
  896. >
  897. inline typename dtl::enable_if_c
  898. < dtl::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
  899. , void>::type
  900. deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
  901. , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
  902. {
  903. typedef typename allocator_traits<Allocator>::value_type value_type;
  904. typedef typename dtl::aligned_storage
  905. <MaxTmpBytes, dtl::alignment_of<value_type>::value>::type storage_type;
  906. storage_type storage;
  907. const std::size_t n_i_bytes = sizeof(value_type)*n_i;
  908. void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f));
  909. void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f));
  910. void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage.data));
  911. std::memcpy(stora_ptr, large_ptr, n_i_bytes);
  912. std::memcpy(large_ptr, short_ptr, n_i_bytes);
  913. std::memcpy(short_ptr, stora_ptr, n_i_bytes);
  914. boost::container::iterator_advance(large_range_f, n_i);
  915. boost::container::iterator_advance(short_range_f, n_i);
  916. boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
  917. boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
  918. }
  919. template
  920. <std::size_t MaxTmpBytes
  921. ,typename Allocator
  922. ,typename F // F models ForwardIterator
  923. ,typename G // G models ForwardIterator
  924. >
  925. inline typename dtl::enable_if_c
  926. < dtl::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
  927. , void>::type
  928. deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
  929. , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
  930. {
  931. typedef typename allocator_traits<Allocator>::value_type value_type;
  932. typedef typename dtl::aligned_storage
  933. <DeepSwapAllocNMaxStorage, dtl::alignment_of<value_type>::value>::type storage_type;
  934. storage_type storage;
  935. const std::size_t sizeof_storage = sizeof(storage);
  936. std::size_t n_i_bytes = sizeof(value_type)*n_i;
  937. char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)));
  938. char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)));
  939. char *stora_ptr = static_cast<char*>(static_cast<void*>(storage.data));
  940. std::size_t szt_times = n_i_bytes/sizeof_storage;
  941. const std::size_t szt_rem = n_i_bytes%sizeof_storage;
  942. //Loop unrolling using Duff's device, as it seems it helps on some architectures
  943. const std::size_t Unroll = 4;
  944. std::size_t n = (szt_times + (Unroll-1))/Unroll;
  945. const std::size_t branch_number = (!szt_times)*Unroll + (szt_times % Unroll);
  946. switch(branch_number){
  947. case 4:
  948. break;
  949. case 0: do{
  950. std::memcpy(stora_ptr, large_ptr, sizeof_storage);
  951. std::memcpy(large_ptr, short_ptr, sizeof_storage);
  952. std::memcpy(short_ptr, stora_ptr, sizeof_storage);
  953. large_ptr += sizeof_storage;
  954. short_ptr += sizeof_storage;
  955. BOOST_FALLTHROUGH;
  956. case 3:
  957. std::memcpy(stora_ptr, large_ptr, sizeof_storage);
  958. std::memcpy(large_ptr, short_ptr, sizeof_storage);
  959. std::memcpy(short_ptr, stora_ptr, sizeof_storage);
  960. large_ptr += sizeof_storage;
  961. short_ptr += sizeof_storage;
  962. BOOST_FALLTHROUGH;
  963. case 2:
  964. std::memcpy(stora_ptr, large_ptr, sizeof_storage);
  965. std::memcpy(large_ptr, short_ptr, sizeof_storage);
  966. std::memcpy(short_ptr, stora_ptr, sizeof_storage);
  967. large_ptr += sizeof_storage;
  968. short_ptr += sizeof_storage;
  969. BOOST_FALLTHROUGH;
  970. case 1:
  971. std::memcpy(stora_ptr, large_ptr, sizeof_storage);
  972. std::memcpy(large_ptr, short_ptr, sizeof_storage);
  973. std::memcpy(short_ptr, stora_ptr, sizeof_storage);
  974. large_ptr += sizeof_storage;
  975. short_ptr += sizeof_storage;
  976. } while(--n);
  977. }
  978. std::memcpy(stora_ptr, large_ptr, szt_rem);
  979. std::memcpy(large_ptr, short_ptr, szt_rem);
  980. std::memcpy(short_ptr, stora_ptr, szt_rem);
  981. boost::container::iterator_advance(large_range_f, n_i);
  982. boost::container::iterator_advance(short_range_f, n_i);
  983. boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
  984. boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
  985. }
  986. //////////////////////////////////////////////////////////////////////////////
  987. //
  988. // copy_assign_range_alloc_n
  989. //
  990. //////////////////////////////////////////////////////////////////////////////
  991. template
  992. <typename Allocator
  993. ,typename I // F models InputIterator
  994. ,typename O // G models OutputIterator
  995. >
  996. void copy_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
  997. , O out_start, typename allocator_traits<Allocator>::size_type n_o )
  998. {
  999. if (n_o < n_i){
  1000. inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw
  1001. boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
  1002. }
  1003. else{
  1004. out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
  1005. boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
  1006. }
  1007. }
  1008. //////////////////////////////////////////////////////////////////////////////
  1009. //
  1010. // move_assign_range_alloc_n
  1011. //
  1012. //////////////////////////////////////////////////////////////////////////////
  1013. template
  1014. <typename Allocator
  1015. ,typename I // F models InputIterator
  1016. ,typename O // G models OutputIterator
  1017. >
  1018. void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
  1019. , O out_start, typename allocator_traits<Allocator>::size_type n_o )
  1020. {
  1021. if (n_o < n_i){
  1022. inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw
  1023. boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
  1024. }
  1025. else{
  1026. out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
  1027. boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
  1028. }
  1029. }
  1030. } //namespace container {
  1031. } //namespace boost {
  1032. #if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
  1033. #pragma GCC diagnostic pop
  1034. #endif
  1035. #endif //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP