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
18 #include <boost/container/detail/config_begin.hpp>
19 #include <boost/container/detail/workaround.hpp>
21 #include <boost/container/allocator_traits.hpp>
22 #include <boost/container/detail/destroyers.hpp>
23 #include <boost/aligned_storage.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/container/detail/mpl.hpp>
26 #include <boost/container/detail/utilities.hpp>
27 #include <boost/container/detail/type_traits.hpp>
28 #include <boost/container/detail/iterators.hpp>
29 #include <iterator> //std::iterator_traits
30 #include <boost/assert.hpp>
31 #include <boost/core/no_exceptions_support.hpp>
33 namespace boost { namespace container { namespace container_detail {
35 template<class A, class FwdIt, class Iterator>
36 struct move_insert_range_proxy
38 typedef typename allocator_traits<A>::size_type size_type;
39 typedef typename allocator_traits<A>::value_type value_type;
41 explicit move_insert_range_proxy(FwdIt first)
45 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
47 this->first_ = ::boost::container::uninitialized_move_alloc_n_source
48 (a, this->first_, n, p);
51 void copy_n_and_update(A &, Iterator p, size_type n)
53 this->first_ = ::boost::container::move_n_source(this->first_, n, p);
60 template<class A, class FwdIt, class Iterator>
61 struct insert_range_proxy
63 typedef typename allocator_traits<A>::size_type size_type;
64 typedef typename allocator_traits<A>::value_type value_type;
66 explicit insert_range_proxy(FwdIt first)
70 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
72 this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
75 void copy_n_and_update(A &, Iterator p, size_type n)
77 this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
84 template<class A, class Iterator>
85 struct insert_n_copies_proxy
87 typedef typename allocator_traits<A>::size_type size_type;
88 typedef typename allocator_traits<A>::value_type value_type;
90 explicit insert_n_copies_proxy(const value_type &v)
94 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
95 { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
97 void copy_n_and_update(A &, Iterator p, size_type n) const
99 for (; 0 < n; --n, ++p){
104 const value_type &v_;
107 template<class A, class Iterator>
108 struct insert_value_initialized_n_proxy
110 typedef ::boost::container::allocator_traits<A> alloc_traits;
111 typedef typename allocator_traits<A>::size_type size_type;
112 typedef typename allocator_traits<A>::value_type value_type;
114 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
115 { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
117 void copy_n_and_update(A &, Iterator, size_type) const
118 { BOOST_ASSERT(false); }
121 template<class A, class Iterator>
122 struct insert_default_initialized_n_proxy
124 typedef ::boost::container::allocator_traits<A> alloc_traits;
125 typedef typename allocator_traits<A>::size_type size_type;
126 typedef typename allocator_traits<A>::value_type value_type;
128 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
129 { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
131 void copy_n_and_update(A &, Iterator, size_type) const
132 { BOOST_ASSERT(false); }
135 template<class A, class Iterator>
136 struct insert_copy_proxy
138 typedef boost::container::allocator_traits<A> alloc_traits;
139 typedef typename alloc_traits::size_type size_type;
140 typedef typename alloc_traits::value_type value_type;
142 explicit insert_copy_proxy(const value_type &v)
146 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
148 BOOST_ASSERT(n == 1); (void)n;
149 alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
152 void copy_n_and_update(A &, Iterator p, size_type n) const
154 BOOST_ASSERT(n == 1); (void)n;
158 const value_type &v_;
162 template<class A, class Iterator>
163 struct insert_move_proxy
165 typedef boost::container::allocator_traits<A> alloc_traits;
166 typedef typename alloc_traits::size_type size_type;
167 typedef typename alloc_traits::value_type value_type;
169 explicit insert_move_proxy(value_type &v)
173 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
175 BOOST_ASSERT(n == 1); (void)n;
176 alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
179 void copy_n_and_update(A &, Iterator p, size_type n) const
181 BOOST_ASSERT(n == 1); (void)n;
182 *p = ::boost::move(v_);
188 template<class It, class A>
189 insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
191 return insert_move_proxy<A, It>(v);
194 template<class It, class A>
195 insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v)
197 return insert_copy_proxy<A, It>(v);
200 }}} //namespace boost { namespace container { namespace container_detail {
202 #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
204 #include <boost/container/detail/variadic_templates_tools.hpp>
205 #include <boost/move/utility_core.hpp>
207 //#include <iostream> //For debugging purposes
210 namespace container {
211 namespace container_detail {
213 template<class A, class Iterator, class ...Args>
214 struct insert_non_movable_emplace_proxy
216 typedef boost::container::allocator_traits<A> alloc_traits;
217 typedef typename alloc_traits::size_type size_type;
218 typedef typename alloc_traits::value_type value_type;
220 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
222 explicit insert_non_movable_emplace_proxy(Args&&... args)
226 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
227 { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
230 template<int ...IdxPack>
231 void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
233 BOOST_ASSERT(n == 1); (void)n;
234 alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
238 tuple<Args&...> args_;
241 template<class A, class Iterator, class ...Args>
242 struct insert_emplace_proxy
243 : public insert_non_movable_emplace_proxy<A, Iterator, Args...>
245 typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
246 typedef boost::container::allocator_traits<A> alloc_traits;
247 typedef typename base_t::value_type value_type;
248 typedef typename base_t::size_type size_type;
249 typedef typename base_t::index_tuple_t index_tuple_t;
251 explicit insert_emplace_proxy(Args&&... args)
252 : base_t(::boost::forward<Args>(args)...)
255 void copy_n_and_update(A &a, Iterator p, size_type n)
256 { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
260 template<int ...IdxPack>
261 void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
263 BOOST_ASSERT(n ==1); (void)n;
264 aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
265 value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
266 alloc_traits::construct(a, vp,
267 ::boost::forward<Args>(get<IdxPack>(this->args_))...);
269 *p = ::boost::move(*vp);
272 alloc_traits::destroy(a, vp);
276 alloc_traits::destroy(a, vp);
280 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
281 template<class A, class Iterator>
282 struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
283 : public insert_move_proxy<A, Iterator>
285 explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v)
286 : insert_move_proxy<A, Iterator>(v)
290 //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
291 //compiler error C2752 (
\93more than one partial specialization matches
\94).
292 //Any problem is solvable with an extra layer of indirection? ;-)
293 template<class A, class Iterator>
294 struct insert_emplace_proxy<A, Iterator
295 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
297 : public insert_copy_proxy<A, Iterator>
299 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
300 : insert_copy_proxy<A, Iterator>(v)
304 template<class A, class Iterator>
305 struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
306 : public insert_copy_proxy<A, Iterator>
308 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
309 : insert_copy_proxy<A, Iterator>(v)
313 template<class A, class Iterator>
314 struct insert_emplace_proxy<A, Iterator
315 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
317 : public insert_copy_proxy<A, Iterator>
319 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
320 : insert_copy_proxy<A, Iterator>(v)
324 }}} //namespace boost { namespace container { namespace container_detail {
326 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
328 #include <boost/container/detail/preprocessor.hpp>
329 #include <boost/container/detail/value_init.hpp>
332 namespace container {
333 namespace container_detail {
335 #define BOOST_PP_LOCAL_MACRO(N) \
336 template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
337 struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
339 typedef boost::container::allocator_traits<A> alloc_traits; \
340 typedef typename alloc_traits::size_type size_type; \
341 typedef typename alloc_traits::value_type value_type; \
343 explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
344 ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
345 BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
348 void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \
350 BOOST_ASSERT(n == 1); (void)n; \
351 alloc_traits::construct \
352 ( a, iterator_to_raw_pointer(p) \
353 BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
357 void copy_n_and_update(A &, Iterator, size_type) \
358 { BOOST_ASSERT(false); } \
361 BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
364 template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
365 struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
366 : BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
367 < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
369 typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
370 <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
371 typedef typename base_t::value_type value_type; \
372 typedef typename base_t::size_type size_type; \
373 typedef boost::container::allocator_traits<A> alloc_traits; \
375 explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
376 ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
377 : base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
380 void copy_n_and_update(A &a, Iterator p, size_type n) \
382 BOOST_ASSERT(n == 1); (void)n; \
383 aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
384 value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
385 alloc_traits::construct(a, vp \
386 BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
388 *p = ::boost::move(*vp); \
391 alloc_traits::destroy(a, vp); \
395 alloc_traits::destroy(a, vp); \
399 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
400 #include BOOST_PP_LOCAL_ITERATE()
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 A, class Iterator>
406 struct insert_emplace_proxy_arg1<A, Iterator, ::boost::rv<typename boost::container::allocator_traits<A>::value_type> >
407 : public insert_move_proxy<A, Iterator>
409 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v)
410 : insert_move_proxy<A, Iterator>(v)
414 template<class A, class Iterator>
415 struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
416 : public insert_copy_proxy<A, Iterator>
418 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
419 : insert_copy_proxy<A, 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 A, class Iterator>
427 struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
428 : public insert_move_proxy<A, Iterator>
430 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v)
431 : insert_move_proxy<A, Iterator>(v)
435 //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
436 //compiler error C2752 (
\93more than one partial specialization matches
\94).
437 //Any problem is solvable with an extra layer of indirection? ;-)
438 template<class A, class Iterator>
439 struct insert_emplace_proxy_arg1<A, Iterator
440 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
442 : public insert_copy_proxy<A, Iterator>
444 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
445 : insert_copy_proxy<A, Iterator>(v)
449 template<class A, class Iterator>
450 struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
451 : public insert_copy_proxy<A, Iterator>
453 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
454 : insert_copy_proxy<A, Iterator>(v)
458 template<class A, class Iterator>
459 struct insert_emplace_proxy_arg1<A, Iterator
460 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
462 : public insert_copy_proxy<A, Iterator>
464 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
465 : insert_copy_proxy<A, Iterator>(v)
471 }}} //namespace boost { namespace container { namespace container_detail {
473 #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
475 #include <boost/container/detail/config_end.hpp>
477 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP