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 BOOST_CONTAINER_FORCEINLINE explicit move_insert_range_proxy(FwdIt first)
56 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE explicit insert_range_proxy(FwdIt first)
81 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE explicit insert_n_copies_proxy(const value_type &v)
105 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
117 const value_type &v_;
120 template<class Allocator, class Iterator>
121 struct insert_value_initialized_n_proxy
123 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
124 typedef typename allocator_traits<Allocator>::size_type size_type;
125 typedef typename allocator_traits<Allocator>::value_type value_type;
126 typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
128 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
129 { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
131 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
136 value_type *vp = reinterpret_cast<value_type *>(v.data);
137 alloc_traits::construct(a, vp);
138 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
139 *p = ::boost::move(*vp);
145 template<class Allocator, class Iterator>
146 struct insert_default_initialized_n_proxy
148 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
149 typedef typename allocator_traits<Allocator>::size_type size_type;
150 typedef typename allocator_traits<Allocator>::value_type value_type;
151 typedef typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type storage_t;
153 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
154 { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
156 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
158 if(!is_pod<value_type>::value){
161 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
162 value_type *vp = reinterpret_cast<value_type *>(v.data);
163 alloc_traits::construct(a, vp, default_init);
164 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
165 *p = ::boost::move(*vp);
172 template<class Allocator, class Iterator>
173 struct insert_copy_proxy
175 typedef boost::container::allocator_traits<Allocator> alloc_traits;
176 typedef typename alloc_traits::size_type size_type;
177 typedef typename alloc_traits::value_type value_type;
179 static const bool single_value = true;
181 BOOST_CONTAINER_FORCEINLINE explicit insert_copy_proxy(const value_type &v)
185 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
187 BOOST_ASSERT(n == 1); (void)n;
188 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
191 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
193 BOOST_ASSERT(n == 1); (void)n;
197 const value_type &v_;
201 template<class Allocator, class Iterator>
202 struct insert_move_proxy
204 typedef boost::container::allocator_traits<Allocator> alloc_traits;
205 typedef typename alloc_traits::size_type size_type;
206 typedef typename alloc_traits::value_type value_type;
208 static const bool single_value = true;
210 BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
214 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
216 BOOST_ASSERT(n == 1); (void)n;
217 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
220 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
222 BOOST_ASSERT(n == 1); (void)n;
223 *p = ::boost::move(v_);
229 template<class It, class Allocator>
230 BOOST_CONTAINER_FORCEINLINE insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
232 return insert_move_proxy<Allocator, It>(v);
235 template<class It, class Allocator>
236 BOOST_CONTAINER_FORCEINLINE insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
238 return insert_copy_proxy<Allocator, It>(v);
241 }}} //namespace boost { namespace container { namespace dtl {
243 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
245 #include <boost/container/detail/variadic_templates_tools.hpp>
246 #include <boost/move/utility_core.hpp>
249 namespace container {
252 template<class Allocator, class Iterator, class ...Args>
253 struct insert_nonmovable_emplace_proxy
255 typedef boost::container::allocator_traits<Allocator> alloc_traits;
256 typedef typename alloc_traits::size_type size_type;
257 typedef typename alloc_traits::value_type value_type;
258 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
260 static const bool single_value = true;
262 BOOST_CONTAINER_FORCEINLINE explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
266 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
267 { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
270 template<std::size_t ...IdxPack>
271 BOOST_CONTAINER_FORCEINLINE void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
273 BOOST_ASSERT(n == 1); (void)n;
274 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
278 tuple<Args&...> args_;
281 template<class Allocator, class Iterator, class ...Args>
282 struct insert_emplace_proxy
283 : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
285 typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t;
286 typedef boost::container::allocator_traits<Allocator> alloc_traits;
287 typedef typename base_t::value_type value_type;
288 typedef typename base_t::size_type size_type;
289 typedef typename base_t::index_tuple_t index_tuple_t;
291 static const bool single_value = true;
293 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
294 : base_t(::boost::forward<Args>(args)...)
297 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &a, Iterator p, size_type n)
298 { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
302 template<std::size_t ...IdxPack>
303 BOOST_CONTAINER_FORCEINLINE void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
305 BOOST_ASSERT(n ==1); (void)n;
306 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
307 value_type *vp = reinterpret_cast<value_type *>(v.data);
308 alloc_traits::construct(a, vp, ::boost::forward<Args>(get<IdxPack>(this->args_))...);
310 *p = ::boost::move(*vp);
313 alloc_traits::destroy(a, vp);
317 alloc_traits::destroy(a, vp);
321 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
322 template<class Allocator, class Iterator>
323 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
324 : public insert_move_proxy<Allocator, Iterator>
326 static const bool single_value = true;
328 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
329 : insert_move_proxy<Allocator, Iterator>(v)
333 //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
334 //compiler error C2752 ("more than one partial specialization matches").
335 //Any problem is solvable with an extra layer of indirection? ;-)
336 template<class Allocator, class Iterator>
337 struct insert_emplace_proxy<Allocator, Iterator
338 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
340 : public insert_copy_proxy<Allocator, Iterator>
343 static const bool single_value = true;
345 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
346 : insert_copy_proxy<Allocator, Iterator>(v)
350 template<class Allocator, class Iterator>
351 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
352 : public insert_copy_proxy<Allocator, Iterator>
354 static const bool single_value = true;
356 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
357 : insert_copy_proxy<Allocator, Iterator>(v)
361 template<class Allocator, class Iterator>
362 struct insert_emplace_proxy<Allocator, Iterator
363 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
365 : public insert_copy_proxy<Allocator, Iterator>
367 static const bool single_value = true;
369 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
370 : insert_copy_proxy<Allocator, Iterator>(v)
374 }}} //namespace boost { namespace container { namespace dtl {
376 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
378 #include <boost/container/detail/value_init.hpp>
381 namespace container {
384 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
385 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
386 struct insert_nonmovable_emplace_proxy##N\
388 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
389 typedef typename alloc_traits::size_type size_type;\
390 typedef typename alloc_traits::value_type value_type;\
392 static const bool single_value = true;\
394 BOOST_CONTAINER_FORCEINLINE explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
395 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
397 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
399 BOOST_ASSERT(n == 1); (void)n;\
400 alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
403 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator, size_type)\
404 { BOOST_ASSERT(false); }\
410 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
411 struct insert_emplace_proxy_arg##N\
412 : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
414 typedef insert_nonmovable_emplace_proxy##N\
415 < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
416 typedef typename base_t::value_type value_type;\
417 typedef typename base_t::size_type size_type;\
418 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
420 static const bool single_value = true;\
422 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
423 : base_t(BOOST_MOVE_FWD##N){}\
425 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
427 BOOST_ASSERT(n == 1); (void)n;\
428 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
429 value_type *vp = reinterpret_cast<value_type *>(v.data);\
430 alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
432 *p = ::boost::move(*vp);\
435 alloc_traits::destroy(a, vp);\
439 alloc_traits::destroy(a, vp);\
443 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
444 #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
446 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
448 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
449 template<class Allocator, class Iterator>
450 struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
451 : public insert_move_proxy<Allocator, Iterator>
453 static const bool single_value = true;
455 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
456 : insert_move_proxy<Allocator, Iterator>(v)
460 template<class Allocator, class Iterator>
461 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
462 : public insert_copy_proxy<Allocator, Iterator>
464 static const bool single_value = true;
466 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
467 : insert_copy_proxy<Allocator, Iterator>(v)
471 #else //e.g. MSVC10 & MSVC11
473 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
474 template<class Allocator, class Iterator>
475 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
476 : public insert_move_proxy<Allocator, Iterator>
478 static const bool single_value = true;
480 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
481 : insert_move_proxy<Allocator, Iterator>(v)
485 //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
486 //compiler error C2752 ("more than one partial specialization matches").
487 //Any problem is solvable with an extra layer of indirection? ;-)
488 template<class Allocator, class Iterator>
489 struct insert_emplace_proxy_arg1<Allocator, Iterator
490 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
492 : public insert_copy_proxy<Allocator, Iterator>
494 static const bool single_value = true;
496 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
497 : insert_copy_proxy<Allocator, Iterator>(v)
501 template<class Allocator, class Iterator>
502 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
503 : public insert_copy_proxy<Allocator, Iterator>
505 static const bool single_value = true;
507 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
508 : insert_copy_proxy<Allocator, Iterator>(v)
512 template<class Allocator, class Iterator>
513 struct insert_emplace_proxy_arg1<Allocator, Iterator
514 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
516 : public insert_copy_proxy<Allocator, Iterator>
518 static const bool single_value = true;
520 BOOST_CONTAINER_FORCEINLINE explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
521 : insert_copy_proxy<Allocator, Iterator>(v)
527 }}} //namespace boost { namespace container { namespace dtl {
529 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
531 namespace boost { namespace container { namespace dtl {
534 struct has_single_value
537 struct two {char array_[2];};
538 template<bool Arg> struct wrapper;
539 template <class U> static two test(int, ...);
540 template <class U> static char test(int, const wrapper<U::single_value>*);
542 static const bool value = sizeof(test<T>(0, 0)) == 1;
546 template<class InsertionProxy, bool = has_single_value<InsertionProxy>::value>
547 struct is_single_value_proxy_impl
549 static const bool value = InsertionProxy::single_value;
552 template<class InsertionProxy>
553 struct is_single_value_proxy_impl<InsertionProxy, false>
555 static const bool value = false;
558 template<class InsertionProxy>
559 struct is_single_value_proxy
560 : is_single_value_proxy_impl<InsertionProxy>
563 }}} //namespace boost { namespace container { namespace dtl {
565 #include <boost/container/detail/config_end.hpp>
567 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP