1 //////////////////////////////////////////////////////////////////////////////
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)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
12 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
26 #include <boost/container/allocator_traits.hpp>
28 #include <boost/container/detail/copy_move_algo.hpp>
29 #include <boost/container/detail/destroyers.hpp>
30 #include <boost/container/detail/mpl.hpp>
31 #include <boost/container/detail/type_traits.hpp>
32 #include <boost/container/detail/iterator.hpp>
33 #include <boost/container/detail/iterators.hpp>
34 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
35 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
36 #include <boost/move/detail/fwd_macros.hpp>
39 #include <boost/move/utility_core.hpp>
41 #include <boost/assert.hpp>
42 #include <boost/core/no_exceptions_support.hpp>
44 namespace boost { namespace container { namespace dtl {
46 template<class Allocator, class FwdIt, class Iterator>
47 struct move_insert_range_proxy
49 typedef typename allocator_traits<Allocator>::size_type size_type;
50 typedef typename allocator_traits<Allocator>::value_type value_type;
52 explicit move_insert_range_proxy(FwdIt first)
56 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
58 this->first_ = ::boost::container::uninitialized_move_alloc_n_source
59 (a, this->first_, n, p);
62 void copy_n_and_update(Allocator &, Iterator p, size_type n)
64 this->first_ = ::boost::container::move_n_source(this->first_, n, p);
71 template<class Allocator, class FwdIt, class Iterator>
72 struct insert_range_proxy
74 typedef typename allocator_traits<Allocator>::size_type size_type;
75 typedef typename allocator_traits<Allocator>::value_type value_type;
77 explicit insert_range_proxy(FwdIt first)
81 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
83 this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
86 void copy_n_and_update(Allocator &, Iterator p, size_type n)
88 this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
95 template<class Allocator, class Iterator>
96 struct insert_n_copies_proxy
98 typedef typename allocator_traits<Allocator>::size_type size_type;
99 typedef typename allocator_traits<Allocator>::value_type value_type;
101 explicit insert_n_copies_proxy(const value_type &v)
105 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
106 { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
108 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
110 for (; 0 < n; --n, ++p){
115 const value_type &v_;
118 template<class Allocator, class Iterator>
119 struct insert_value_initialized_n_proxy
121 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
122 typedef typename allocator_traits<Allocator>::size_type size_type;
123 typedef typename allocator_traits<Allocator>::value_type value_type;
125 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
126 { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
128 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
130 for (; 0 < n; --n, ++p){
131 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
132 value_type *vp = reinterpret_cast<value_type *>(v.data);
133 alloc_traits::construct(a, vp);
134 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
135 *p = ::boost::move(*vp);
140 template<class Allocator, class Iterator>
141 struct insert_default_initialized_n_proxy
143 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
144 typedef typename allocator_traits<Allocator>::size_type size_type;
145 typedef typename allocator_traits<Allocator>::value_type value_type;
147 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
148 { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
150 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
152 if(!is_pod<value_type>::value){
153 for (; 0 < n; --n, ++p){
154 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
155 value_type *vp = reinterpret_cast<value_type *>(v.data);
156 alloc_traits::construct(a, vp, default_init);
157 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
158 *p = ::boost::move(*vp);
164 template<class Allocator, class Iterator>
165 struct insert_copy_proxy
167 typedef boost::container::allocator_traits<Allocator> alloc_traits;
168 typedef typename alloc_traits::size_type size_type;
169 typedef typename alloc_traits::value_type value_type;
171 explicit insert_copy_proxy(const value_type &v)
175 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
177 BOOST_ASSERT(n == 1); (void)n;
178 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
181 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
183 BOOST_ASSERT(n == 1); (void)n;
187 const value_type &v_;
191 template<class Allocator, class Iterator>
192 struct insert_move_proxy
194 typedef boost::container::allocator_traits<Allocator> alloc_traits;
195 typedef typename alloc_traits::size_type size_type;
196 typedef typename alloc_traits::value_type value_type;
198 BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
202 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
204 BOOST_ASSERT(n == 1); (void)n;
205 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
208 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
210 BOOST_ASSERT(n == 1); (void)n;
211 *p = ::boost::move(v_);
217 template<class It, class Allocator>
218 insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
220 return insert_move_proxy<Allocator, It>(v);
223 template<class It, class Allocator>
224 insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
226 return insert_copy_proxy<Allocator, It>(v);
229 }}} //namespace boost { namespace container { namespace dtl {
231 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
233 #include <boost/container/detail/variadic_templates_tools.hpp>
234 #include <boost/move/utility_core.hpp>
237 namespace container {
240 template<class Allocator, class Iterator, class ...Args>
241 struct insert_nonmovable_emplace_proxy
243 typedef boost::container::allocator_traits<Allocator> alloc_traits;
244 typedef typename alloc_traits::size_type size_type;
245 typedef typename alloc_traits::value_type value_type;
247 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
249 explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
253 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
254 { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
257 template<std::size_t ...IdxPack>
258 void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
260 BOOST_ASSERT(n == 1); (void)n;
261 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
265 tuple<Args&...> args_;
268 template<class Allocator, class Iterator, class ...Args>
269 struct insert_emplace_proxy
270 : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
272 typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t;
273 typedef boost::container::allocator_traits<Allocator> alloc_traits;
274 typedef typename base_t::value_type value_type;
275 typedef typename base_t::size_type size_type;
276 typedef typename base_t::index_tuple_t index_tuple_t;
278 explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
279 : base_t(::boost::forward<Args>(args)...)
282 void copy_n_and_update(Allocator &a, Iterator p, size_type n)
283 { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
287 template<std::size_t ...IdxPack>
288 void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
290 BOOST_ASSERT(n ==1); (void)n;
291 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
292 value_type *vp = reinterpret_cast<value_type *>(v.data);
293 alloc_traits::construct(a, vp,
294 ::boost::forward<Args>(get<IdxPack>(this->args_))...);
296 *p = ::boost::move(*vp);
299 alloc_traits::destroy(a, vp);
303 alloc_traits::destroy(a, vp);
307 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
308 template<class Allocator, class Iterator>
309 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
310 : public insert_move_proxy<Allocator, Iterator>
312 explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
313 : insert_move_proxy<Allocator, Iterator>(v)
317 //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
318 //compiler error C2752 ("more than one partial specialization matches").
319 //Any problem is solvable with an extra layer of indirection? ;-)
320 template<class Allocator, class Iterator>
321 struct insert_emplace_proxy<Allocator, Iterator
322 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
324 : public insert_copy_proxy<Allocator, Iterator>
326 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
327 : insert_copy_proxy<Allocator, Iterator>(v)
331 template<class Allocator, class Iterator>
332 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
333 : public insert_copy_proxy<Allocator, Iterator>
335 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
336 : insert_copy_proxy<Allocator, Iterator>(v)
340 template<class Allocator, class Iterator>
341 struct insert_emplace_proxy<Allocator, Iterator
342 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
344 : public insert_copy_proxy<Allocator, Iterator>
346 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
347 : insert_copy_proxy<Allocator, Iterator>(v)
351 }}} //namespace boost { namespace container { namespace dtl {
353 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
355 #include <boost/container/detail/value_init.hpp>
358 namespace container {
361 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
362 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
363 struct insert_nonmovable_emplace_proxy##N\
365 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
366 typedef typename alloc_traits::size_type size_type;\
367 typedef typename alloc_traits::value_type value_type;\
369 explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
370 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
372 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
374 BOOST_ASSERT(n == 1); (void)n;\
375 alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
378 void copy_n_and_update(Allocator &, Iterator, size_type)\
379 { BOOST_ASSERT(false); }\
385 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
386 struct insert_emplace_proxy_arg##N\
387 : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
389 typedef insert_nonmovable_emplace_proxy##N\
390 < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
391 typedef typename base_t::value_type value_type;\
392 typedef typename base_t::size_type size_type;\
393 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
395 explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
396 : base_t(BOOST_MOVE_FWD##N){}\
398 void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
400 BOOST_ASSERT(n == 1); (void)n;\
401 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
402 BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
403 value_type *vp = reinterpret_cast<value_type *>(v.data);\
404 alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
406 *p = ::boost::move(*vp);\
409 alloc_traits::destroy(a, vp);\
413 alloc_traits::destroy(a, vp);\
417 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
418 #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
420 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
422 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
423 template<class Allocator, class Iterator>
424 struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
425 : public insert_move_proxy<Allocator, Iterator>
427 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
428 : insert_move_proxy<Allocator, Iterator>(v)
432 template<class Allocator, class Iterator>
433 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
434 : public insert_copy_proxy<Allocator, Iterator>
436 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
437 : insert_copy_proxy<Allocator, Iterator>(v)
441 #else //e.g. MSVC10 & MSVC11
443 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
444 template<class Allocator, class Iterator>
445 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
446 : public insert_move_proxy<Allocator, Iterator>
448 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
449 : insert_move_proxy<Allocator, Iterator>(v)
453 //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
454 //compiler error C2752 ("more than one partial specialization matches").
455 //Any problem is solvable with an extra layer of indirection? ;-)
456 template<class Allocator, class Iterator>
457 struct insert_emplace_proxy_arg1<Allocator, Iterator
458 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
460 : public insert_copy_proxy<Allocator, Iterator>
462 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
463 : insert_copy_proxy<Allocator, Iterator>(v)
467 template<class Allocator, class Iterator>
468 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
469 : public insert_copy_proxy<Allocator, Iterator>
471 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
472 : insert_copy_proxy<Allocator, Iterator>(v)
476 template<class Allocator, class Iterator>
477 struct insert_emplace_proxy_arg1<Allocator, Iterator
478 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
480 : public insert_copy_proxy<Allocator, Iterator>
482 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
483 : insert_copy_proxy<Allocator, Iterator>(v)
489 }}} //namespace boost { namespace container { namespace dtl {
491 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
493 #include <boost/container/detail/config_end.hpp>
495 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP