advanced_insert_int.hpp 18 KB

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