utilities.hpp 37 KB

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