copy_move_algo.hpp 41 KB

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