advanced_insert_int.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2008-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_ADVANCED_INSERT_INT_HPP
  11. #define BOOST_CONTAINER_ADVANCED_INSERT_INT_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. #include <boost/container/detail/config_begin.hpp>
  19. #include <boost/container/detail/workaround.hpp>
  20. // container
  21. #include <boost/container/allocator_traits.hpp>
  22. // container/detail
  23. #include <boost/container/detail/copy_move_algo.hpp>
  24. #include <boost/container/detail/destroyers.hpp>
  25. #include <boost/container/detail/mpl.hpp>
  26. #include <boost/container/detail/type_traits.hpp>
  27. #include <boost/container/detail/iterator.hpp>
  28. #include <boost/container/detail/iterators.hpp>
  29. #include <boost/move/detail/iterator_to_raw_pointer.hpp>
  30. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  31. #include <boost/move/detail/fwd_macros.hpp>
  32. #endif
  33. // move
  34. #include <boost/move/utility_core.hpp>
  35. #include <boost/move/detail/force_ptr.hpp>
  36. // other
  37. #include <boost/assert.hpp>
  38. namespace boost { namespace container { namespace dtl {
  39. template<class Allocator, class FwdIt>
  40. struct move_insert_range_proxy
  41. {
  42. typedef typename allocator_traits<Allocator>::value_type value_type;
  43. inline explicit move_insert_range_proxy(FwdIt first)
  44. : first_(first)
  45. {}
  46. template<class Iterator>
  47. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
  48. {
  49. this->first_ = ::boost::container::uninitialized_move_alloc_n_source
  50. (a, this->first_, n, p);
  51. }
  52. template<class Iterator>
  53. inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n)
  54. {
  55. this->first_ = ::boost::container::move_n_source(this->first_, n, p);
  56. }
  57. FwdIt first_;
  58. };
  59. template<class Allocator, class FwdIt>
  60. struct insert_range_proxy
  61. {
  62. typedef typename allocator_traits<Allocator>::value_type value_type;
  63. inline explicit insert_range_proxy(FwdIt first)
  64. : first_(first)
  65. {}
  66. template<class Iterator>
  67. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
  68. {
  69. this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
  70. }
  71. template<class Iterator>
  72. inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n)
  73. {
  74. this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
  75. }
  76. FwdIt first_;
  77. };
  78. template<class Allocator>
  79. struct insert_n_copies_proxy
  80. {
  81. typedef typename allocator_traits<Allocator>::value_type value_type;
  82. inline explicit insert_n_copies_proxy(const value_type &v)
  83. : v_(v)
  84. {}
  85. template<class Iterator>
  86. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  87. { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
  88. template<class Iterator>
  89. inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
  90. {
  91. while (n){
  92. --n;
  93. *p = v_;
  94. ++p;
  95. }
  96. }
  97. const value_type &v_;
  98. };
  99. template<class Allocator>
  100. struct insert_value_initialized_n_proxy
  101. {
  102. typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
  103. typedef typename allocator_traits<Allocator>::value_type value_type;
  104. typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
  105. template<class Iterator>
  106. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  107. { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
  108. template<class Iterator>
  109. void copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  110. {
  111. while (n){
  112. --n;
  113. storage_t v;
  114. alloc_traits::construct(a, move_detail::force_ptr<value_type *>(&v));
  115. value_type *vp = move_detail::force_ptr<value_type *>(&v);
  116. value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
  117. *p = ::boost::move(*vp);
  118. ++p;
  119. }
  120. }
  121. };
  122. template<class Allocator>
  123. struct insert_default_initialized_n_proxy
  124. {
  125. typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
  126. typedef typename allocator_traits<Allocator>::value_type value_type;
  127. typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
  128. template<class Iterator>
  129. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  130. { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
  131. template<class Iterator>
  132. void copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  133. {
  134. if(!is_pod<value_type>::value){
  135. while (n){
  136. --n;
  137. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  138. alloc_traits::construct(a, move_detail::force_ptr<value_type *>(&v), default_init);
  139. value_type *vp = move_detail::force_ptr<value_type *>(&v);
  140. value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
  141. *p = ::boost::move(*vp);
  142. ++p;
  143. }
  144. }
  145. }
  146. };
  147. template<class Allocator>
  148. struct insert_copy_proxy
  149. {
  150. typedef boost::container::allocator_traits<Allocator> alloc_traits;
  151. typedef typename alloc_traits::value_type value_type;
  152. static const bool single_value = true;
  153. inline explicit insert_copy_proxy(const value_type &v)
  154. : v_(v)
  155. {}
  156. template<class Iterator>
  157. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  158. {
  159. BOOST_ASSERT(n == 1); (void)n;
  160. alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
  161. }
  162. template<class Iterator>
  163. inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
  164. {
  165. BOOST_ASSERT(n == 1); (void)n;
  166. *p = v_;
  167. }
  168. const value_type &v_;
  169. };
  170. template<class Allocator>
  171. struct insert_move_proxy
  172. {
  173. typedef boost::container::allocator_traits<Allocator> alloc_traits;
  174. typedef typename alloc_traits::value_type value_type;
  175. static const bool single_value = true;
  176. inline explicit insert_move_proxy(value_type &v)
  177. : v_(v)
  178. {}
  179. template<class Iterator>
  180. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n) const
  181. {
  182. BOOST_ASSERT(n == 1); (void)n;
  183. alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
  184. }
  185. template<class Iterator>
  186. inline void copy_n_and_update(Allocator &, Iterator p, std::size_t n) const
  187. {
  188. BOOST_ASSERT(n == 1); (void)n;
  189. *p = ::boost::move(v_);
  190. }
  191. value_type &v_;
  192. };
  193. template<class It, class Allocator>
  194. inline insert_move_proxy<Allocator> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
  195. {
  196. return insert_move_proxy<Allocator>(v);
  197. }
  198. template<class It, class Allocator>
  199. inline insert_copy_proxy<Allocator> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
  200. {
  201. return insert_copy_proxy<Allocator>(v);
  202. }
  203. }}} //namespace boost { namespace container { namespace dtl {
  204. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  205. #include <boost/container/detail/variadic_templates_tools.hpp>
  206. #include <boost/move/utility_core.hpp>
  207. namespace boost {
  208. namespace container {
  209. namespace dtl {
  210. template<class Allocator, class ...Args>
  211. struct insert_nonmovable_emplace_proxy
  212. {
  213. typedef boost::container::allocator_traits<Allocator> alloc_traits;
  214. typedef typename alloc_traits::value_type value_type;
  215. typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
  216. static const bool single_value = true;
  217. inline explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
  218. : args_(args...)
  219. {}
  220. template<class Iterator>
  221. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
  222. { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
  223. private:
  224. template<std::size_t ...IdxPack, class Iterator>
  225. inline void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, std::size_t n)
  226. {
  227. BOOST_ASSERT(n == 1); (void)n;
  228. alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
  229. }
  230. protected:
  231. tuple<Args&...> args_;
  232. };
  233. template<class Allocator, class ...Args>
  234. struct insert_emplace_proxy
  235. : public insert_nonmovable_emplace_proxy<Allocator, Args...>
  236. {
  237. typedef insert_nonmovable_emplace_proxy<Allocator, Args...> base_t;
  238. typedef boost::container::allocator_traits<Allocator> alloc_traits;
  239. typedef typename base_t::value_type value_type;
  240. typedef typename base_t::index_tuple_t index_tuple_t;
  241. static const bool single_value = true;
  242. inline explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
  243. : base_t(::boost::forward<Args>(args)...)
  244. {}
  245. template<class Iterator>
  246. inline void copy_n_and_update(Allocator &a, Iterator p, std::size_t n)
  247. { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
  248. private:
  249. template<std::size_t ...IdxPack, class Iterator>
  250. inline void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, std::size_t n)
  251. {
  252. BOOST_ASSERT(n ==1); (void)n;
  253. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
  254. alloc_traits::construct(a, move_detail::force_ptr<value_type *>(&v), ::boost::forward<Args>(get<IdxPack>(this->args_))...);
  255. value_type *vp = move_detail::force_ptr<value_type *>(&v);
  256. BOOST_CONTAINER_TRY{
  257. *p = ::boost::move(*vp);
  258. }
  259. BOOST_CONTAINER_CATCH(...){
  260. alloc_traits::destroy(a, vp);
  261. BOOST_CONTAINER_RETHROW
  262. }
  263. BOOST_CONTAINER_CATCH_END
  264. alloc_traits::destroy(a, vp);
  265. }
  266. };
  267. //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
  268. template<class Allocator>
  269. struct insert_emplace_proxy<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
  270. : public insert_move_proxy<Allocator>
  271. {
  272. static const bool single_value = true;
  273. inline explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
  274. : insert_move_proxy<Allocator>(v)
  275. {}
  276. };
  277. //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
  278. //compiler error C2752 ("more than one partial specialization matches").
  279. //Any problem is solvable with an extra layer of indirection? ;-)
  280. template<class Allocator>
  281. struct insert_emplace_proxy<Allocator
  282. , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
  283. >
  284. : public insert_copy_proxy<Allocator>
  285. {
  286. static const bool single_value = true;
  287. inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  288. : insert_copy_proxy<Allocator>(v)
  289. {}
  290. };
  291. template<class Allocator>
  292. struct insert_emplace_proxy<Allocator, typename boost::container::allocator_traits<Allocator>::value_type &>
  293. : public insert_copy_proxy<Allocator>
  294. {
  295. static const bool single_value = true;
  296. inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  297. : insert_copy_proxy<Allocator>(v)
  298. {}
  299. };
  300. template<class Allocator>
  301. struct insert_emplace_proxy<Allocator
  302. , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
  303. >
  304. : public insert_copy_proxy<Allocator>
  305. {
  306. static const bool single_value = true;
  307. inline explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  308. : insert_copy_proxy<Allocator>(v)
  309. {}
  310. };
  311. }}} //namespace boost { namespace container { namespace dtl {
  312. #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  313. #include <boost/container/detail/value_init.hpp>
  314. namespace boost {
  315. namespace container {
  316. namespace dtl {
  317. #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
  318. template< class Allocator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  319. struct insert_nonmovable_emplace_proxy##N\
  320. {\
  321. typedef boost::container::allocator_traits<Allocator> alloc_traits;\
  322. typedef typename alloc_traits::value_type value_type;\
  323. \
  324. static const bool single_value = true;\
  325. \
  326. inline explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
  327. BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
  328. \
  329. template<class Iterator>\
  330. inline void uninitialized_copy_n_and_update(Allocator &a, Iterator p, std::size_t n)\
  331. {\
  332. BOOST_ASSERT(n == 1); (void)n;\
  333. alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
  334. }\
  335. \
  336. template<class Iterator>\
  337. inline void copy_n_and_update(Allocator &, Iterator, std::size_t)\
  338. { BOOST_ASSERT(false); }\
  339. \
  340. protected:\
  341. BOOST_MOVE_MREF##N\
  342. };\
  343. \
  344. template< class Allocator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  345. struct insert_emplace_proxy_arg##N\
  346. : insert_nonmovable_emplace_proxy##N< Allocator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
  347. {\
  348. typedef insert_nonmovable_emplace_proxy##N\
  349. < Allocator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
  350. typedef typename base_t::value_type value_type;\
  351. typedef boost::container::allocator_traits<Allocator> alloc_traits;\
  352. \
  353. static const bool single_value = true;\
  354. \
  355. inline explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
  356. : base_t(BOOST_MOVE_FWD##N){}\
  357. \
  358. template<class Iterator>\
  359. inline void copy_n_and_update(Allocator &a, Iterator p, std::size_t n)\
  360. {\
  361. BOOST_ASSERT(n == 1); (void)n;\
  362. typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
  363. alloc_traits::construct(a, move_detail::force_ptr<value_type *>(&v) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
  364. value_type *vp = move_detail::force_ptr<value_type *>(&v);\
  365. BOOST_CONTAINER_TRY{\
  366. *p = ::boost::move(*vp);\
  367. }\
  368. BOOST_CONTAINER_CATCH(...){\
  369. alloc_traits::destroy(a, vp);\
  370. BOOST_CONTAINER_RETHROW\
  371. }\
  372. BOOST_CONTAINER_CATCH_END\
  373. alloc_traits::destroy(a, vp);\
  374. }\
  375. };\
  376. //
  377. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
  378. #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
  379. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  380. //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
  381. template<class Allocator>
  382. struct insert_emplace_proxy_arg1<Allocator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
  383. : public insert_move_proxy<Allocator>
  384. {
  385. static const bool single_value = true;
  386. inline explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
  387. : insert_move_proxy<Allocator>(v)
  388. {}
  389. };
  390. template<class Allocator>
  391. struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
  392. : public insert_copy_proxy<Allocator>
  393. {
  394. static const bool single_value = true;
  395. inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  396. : insert_copy_proxy<Allocator>(v)
  397. {}
  398. };
  399. #else //e.g. MSVC10 & MSVC11
  400. //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
  401. template<class Allocator>
  402. struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type>
  403. : public insert_move_proxy<Allocator>
  404. {
  405. static const bool single_value = true;
  406. inline explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
  407. : insert_move_proxy<Allocator>(v)
  408. {}
  409. };
  410. //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
  411. //compiler error C2752 ("more than one partial specialization matches").
  412. //Any problem is solvable with an extra layer of indirection? ;-)
  413. template<class Allocator>
  414. struct insert_emplace_proxy_arg1<Allocator
  415. , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
  416. >
  417. : public insert_copy_proxy<Allocator>
  418. {
  419. static const bool single_value = true;
  420. inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  421. : insert_copy_proxy<Allocator>(v)
  422. {}
  423. };
  424. template<class Allocator>
  425. struct insert_emplace_proxy_arg1<Allocator, typename boost::container::allocator_traits<Allocator>::value_type &>
  426. : public insert_copy_proxy<Allocator>
  427. {
  428. static const bool single_value = true;
  429. inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  430. : insert_copy_proxy<Allocator>(v)
  431. {}
  432. };
  433. template<class Allocator>
  434. struct insert_emplace_proxy_arg1<Allocator
  435. , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
  436. >
  437. : public insert_copy_proxy<Allocator>
  438. {
  439. static const bool single_value = true;
  440. inline explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
  441. : insert_copy_proxy<Allocator>(v)
  442. {}
  443. };
  444. #endif
  445. }}} //namespace boost { namespace container { namespace dtl {
  446. #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  447. #include <boost/container/detail/config_end.hpp>
  448. #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP