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 container_detail {
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 &, Iterator, size_type) const
129 { BOOST_ASSERT(false); }
132 template<class Allocator, class Iterator>
133 struct insert_default_initialized_n_proxy
135 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
136 typedef typename allocator_traits<Allocator>::size_type size_type;
137 typedef typename allocator_traits<Allocator>::value_type value_type;
139 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
140 { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
142 void copy_n_and_update(Allocator &, Iterator, size_type) const
143 { BOOST_ASSERT(false); }
146 template<class Allocator, class Iterator>
147 struct insert_copy_proxy
149 typedef boost::container::allocator_traits<Allocator> alloc_traits;
150 typedef typename alloc_traits::size_type size_type;
151 typedef typename alloc_traits::value_type value_type;
153 explicit insert_copy_proxy(const value_type &v)
157 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
159 BOOST_ASSERT(n == 1); (void)n;
160 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
163 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
165 BOOST_ASSERT(n == 1); (void)n;
169 const value_type &v_;
173 template<class Allocator, class Iterator>
174 struct insert_move_proxy
176 typedef boost::container::allocator_traits<Allocator> alloc_traits;
177 typedef typename alloc_traits::size_type size_type;
178 typedef typename alloc_traits::value_type value_type;
180 explicit insert_move_proxy(value_type &v)
184 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
186 BOOST_ASSERT(n == 1); (void)n;
187 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
190 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
192 BOOST_ASSERT(n == 1); (void)n;
193 *p = ::boost::move(v_);
199 template<class It, class Allocator>
200 insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
202 return insert_move_proxy<Allocator, It>(v);
205 template<class It, class Allocator>
206 insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
208 return insert_copy_proxy<Allocator, It>(v);
211 }}} //namespace boost { namespace container { namespace container_detail {
213 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
215 #include <boost/container/detail/variadic_templates_tools.hpp>
216 #include <boost/move/utility_core.hpp>
219 namespace container {
220 namespace container_detail {
222 template<class Allocator, class Iterator, class ...Args>
223 struct insert_nonmovable_emplace_proxy
225 typedef boost::container::allocator_traits<Allocator> alloc_traits;
226 typedef typename alloc_traits::size_type size_type;
227 typedef typename alloc_traits::value_type value_type;
229 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
231 explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
235 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
236 { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
239 template<std::size_t ...IdxPack>
240 void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
242 BOOST_ASSERT(n == 1); (void)n;
243 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
247 tuple<Args&...> args_;
250 template<class Allocator, class Iterator, class ...Args>
251 struct insert_emplace_proxy
252 : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
254 typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t;
255 typedef boost::container::allocator_traits<Allocator> alloc_traits;
256 typedef typename base_t::value_type value_type;
257 typedef typename base_t::size_type size_type;
258 typedef typename base_t::index_tuple_t index_tuple_t;
260 explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
261 : base_t(::boost::forward<Args>(args)...)
264 void copy_n_and_update(Allocator &a, Iterator p, size_type n)
265 { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
269 template<std::size_t ...IdxPack>
270 void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
272 BOOST_ASSERT(n ==1); (void)n;
273 typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
274 value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
275 alloc_traits::construct(a, vp,
276 ::boost::forward<Args>(get<IdxPack>(this->args_))...);
278 *p = ::boost::move(*vp);
281 alloc_traits::destroy(a, vp);
285 alloc_traits::destroy(a, vp);
289 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
290 template<class Allocator, class Iterator>
291 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
292 : public insert_move_proxy<Allocator, Iterator>
294 explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
295 : insert_move_proxy<Allocator, Iterator>(v)
299 //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
300 //compiler error C2752 ("more than one partial specialization matches").
301 //Any problem is solvable with an extra layer of indirection? ;-)
302 template<class Allocator, class Iterator>
303 struct insert_emplace_proxy<Allocator, Iterator
304 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
306 : public insert_copy_proxy<Allocator, Iterator>
308 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
309 : insert_copy_proxy<Allocator, Iterator>(v)
313 template<class Allocator, class Iterator>
314 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
315 : public insert_copy_proxy<Allocator, Iterator>
317 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
318 : insert_copy_proxy<Allocator, Iterator>(v)
322 template<class Allocator, class Iterator>
323 struct insert_emplace_proxy<Allocator, Iterator
324 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
326 : public insert_copy_proxy<Allocator, Iterator>
328 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
329 : insert_copy_proxy<Allocator, Iterator>(v)
333 }}} //namespace boost { namespace container { namespace container_detail {
335 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
337 #include <boost/container/detail/value_init.hpp>
340 namespace container {
341 namespace container_detail {
343 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
344 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
345 struct insert_nonmovable_emplace_proxy##N\
347 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
348 typedef typename alloc_traits::size_type size_type;\
349 typedef typename alloc_traits::value_type value_type;\
351 explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
352 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
354 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
356 BOOST_ASSERT(n == 1); (void)n;\
357 alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
360 void copy_n_and_update(Allocator &, Iterator, size_type)\
361 { BOOST_ASSERT(false); }\
367 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
368 struct insert_emplace_proxy_arg##N\
369 : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
371 typedef insert_nonmovable_emplace_proxy##N\
372 < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
373 typedef typename base_t::value_type value_type;\
374 typedef typename base_t::size_type size_type;\
375 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
377 explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
378 : base_t(BOOST_MOVE_FWD##N){}\
380 void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
382 BOOST_ASSERT(n == 1); (void)n;\
383 typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\
384 BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
385 value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));\
386 alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
388 *p = ::boost::move(*vp);\
391 alloc_traits::destroy(a, vp);\
395 alloc_traits::destroy(a, vp);\
399 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
400 #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
402 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
404 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
405 template<class Allocator, class Iterator>
406 struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
407 : public insert_move_proxy<Allocator, Iterator>
409 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
410 : insert_move_proxy<Allocator, Iterator>(v)
414 template<class Allocator, class Iterator>
415 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
416 : public insert_copy_proxy<Allocator, Iterator>
418 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
419 : insert_copy_proxy<Allocator, Iterator>(v)
423 #else //e.g. MSVC10 & MSVC11
425 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
426 template<class Allocator, class Iterator>
427 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
428 : public insert_move_proxy<Allocator, Iterator>
430 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
431 : insert_move_proxy<Allocator, Iterator>(v)
435 //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
436 //compiler error C2752 ("more than one partial specialization matches").
437 //Any problem is solvable with an extra layer of indirection? ;-)
438 template<class Allocator, class Iterator>
439 struct insert_emplace_proxy_arg1<Allocator, Iterator
440 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
442 : public insert_copy_proxy<Allocator, Iterator>
444 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
445 : insert_copy_proxy<Allocator, Iterator>(v)
449 template<class Allocator, class Iterator>
450 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
451 : public insert_copy_proxy<Allocator, Iterator>
453 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
454 : insert_copy_proxy<Allocator, Iterator>(v)
458 template<class Allocator, class Iterator>
459 struct insert_emplace_proxy_arg1<Allocator, Iterator
460 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
462 : public insert_copy_proxy<Allocator, Iterator>
464 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
465 : insert_copy_proxy<Allocator, Iterator>(v)
471 }}} //namespace boost { namespace container { namespace container_detail {
473 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
475 #include <boost/container/detail/config_end.hpp>
477 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP