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
11#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
12#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
13
14#ifndef BOOST_CONFIG_HPP
15# include <boost/config.hpp>
16#endif
17
18#if defined(BOOST_HAS_PRAGMA_ONCE)
19# pragma once
20#endif
21
22#include <boost/container/detail/config_begin.hpp>
23#include <boost/container/detail/workaround.hpp>
24
25// container
26#include <boost/container/allocator_traits.hpp>
27// container/detail
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>
37#endif
38// move
39#include <boost/move/utility_core.hpp>
40// other
41#include <boost/assert.hpp>
42#include <boost/core/no_exceptions_support.hpp>
43
44namespace boost { namespace container { namespace container_detail {
45
46template<class Allocator, class FwdIt, class Iterator>
47struct move_insert_range_proxy
48{
49 typedef typename allocator_traits<Allocator>::size_type size_type;
50 typedef typename allocator_traits<Allocator>::value_type value_type;
51
52 explicit move_insert_range_proxy(FwdIt first)
53 : first_(first)
54 {}
55
56 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
57 {
58 this->first_ = ::boost::container::uninitialized_move_alloc_n_source
59 (a, this->first_, n, p);
60 }
61
62 void copy_n_and_update(Allocator &, Iterator p, size_type n)
63 {
64 this->first_ = ::boost::container::move_n_source(this->first_, n, p);
65 }
66
67 FwdIt first_;
68};
69
70
71template<class Allocator, class FwdIt, class Iterator>
72struct insert_range_proxy
73{
74 typedef typename allocator_traits<Allocator>::size_type size_type;
75 typedef typename allocator_traits<Allocator>::value_type value_type;
76
77 explicit insert_range_proxy(FwdIt first)
78 : first_(first)
79 {}
80
81 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
82 {
83 this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
84 }
85
86 void copy_n_and_update(Allocator &, Iterator p, size_type n)
87 {
88 this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
89 }
90
91 FwdIt first_;
92};
93
94
95template<class Allocator, class Iterator>
96struct insert_n_copies_proxy
97{
98 typedef typename allocator_traits<Allocator>::size_type size_type;
99 typedef typename allocator_traits<Allocator>::value_type value_type;
100
101 explicit insert_n_copies_proxy(const value_type &v)
102 : v_(v)
103 {}
104
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); }
107
108 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
109 {
110 for (; 0 < n; --n, ++p){
111 *p = v_;
112 }
113 }
114
115 const value_type &v_;
116};
117
118template<class Allocator, class Iterator>
119struct insert_value_initialized_n_proxy
120{
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;
124
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); }
127
128 void copy_n_and_update(Allocator &, Iterator, size_type) const
129 { BOOST_ASSERT(false); }
130};
131
132template<class Allocator, class Iterator>
133struct insert_default_initialized_n_proxy
134{
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;
138
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); }
141
142 void copy_n_and_update(Allocator &, Iterator, size_type) const
143 { BOOST_ASSERT(false); }
144};
145
146template<class Allocator, class Iterator>
147struct insert_copy_proxy
148{
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;
152
153 explicit insert_copy_proxy(const value_type &v)
154 : v_(v)
155 {}
156
157 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
158 {
159 BOOST_ASSERT(n == 1); (void)n;
160 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
161 }
162
163 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
164 {
165 BOOST_ASSERT(n == 1); (void)n;
166 *p =v_;
167 }
168
169 const value_type &v_;
170};
171
172
173template<class Allocator, class Iterator>
174struct insert_move_proxy
175{
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;
179
180 explicit insert_move_proxy(value_type &v)
181 : v_(v)
182 {}
183
184 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
185 {
186 BOOST_ASSERT(n == 1); (void)n;
187 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
188 }
189
190 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
191 {
192 BOOST_ASSERT(n == 1); (void)n;
193 *p = ::boost::move(v_);
194 }
195
196 value_type &v_;
197};
198
199template<class It, class Allocator>
200insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
201{
202 return insert_move_proxy<Allocator, It>(v);
203}
204
205template<class It, class Allocator>
206insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
207{
208 return insert_copy_proxy<Allocator, It>(v);
209}
210
211}}} //namespace boost { namespace container { namespace container_detail {
212
213#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
214
215#include <boost/container/detail/variadic_templates_tools.hpp>
216#include <boost/move/utility_core.hpp>
217
218namespace boost {
219namespace container {
220namespace container_detail {
221
222template<class Allocator, class Iterator, class ...Args>
223struct insert_nonmovable_emplace_proxy
224{
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;
228
229 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
230
231 explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
232 : args_(args...)
233 {}
234
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); }
237
238 private:
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)
241 {
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_))... );
244 }
245
246 protected:
247 tuple<Args&...> args_;
248};
249
250template<class Allocator, class Iterator, class ...Args>
251struct insert_emplace_proxy
252 : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
253{
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;
259
260 explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
261 : base_t(::boost::forward<Args>(args)...)
262 {}
263
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); }
266
267 private:
268
269 template<std::size_t ...IdxPack>
270 void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
271 {
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_))...);
277 BOOST_TRY{
278 *p = ::boost::move(*vp);
279 }
280 BOOST_CATCH(...){
281 alloc_traits::destroy(a, vp);
282 BOOST_RETHROW
283 }
284 BOOST_CATCH_END
285 alloc_traits::destroy(a, vp);
286 }
287};
288
289//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
290template<class Allocator, class Iterator>
291struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
292 : public insert_move_proxy<Allocator, Iterator>
293{
294 explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
295 : insert_move_proxy<Allocator, Iterator>(v)
296 {}
297};
298
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? ;-)
302template<class Allocator, class Iterator>
303struct insert_emplace_proxy<Allocator, Iterator
304 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
305 >
306 : public insert_copy_proxy<Allocator, Iterator>
307{
308 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
309 : insert_copy_proxy<Allocator, Iterator>(v)
310 {}
311};
312
313template<class Allocator, class Iterator>
314struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
315 : public insert_copy_proxy<Allocator, Iterator>
316{
317 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
318 : insert_copy_proxy<Allocator, Iterator>(v)
319 {}
320};
321
322template<class Allocator, class Iterator>
323struct insert_emplace_proxy<Allocator, Iterator
324 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
325 >
326 : public insert_copy_proxy<Allocator, Iterator>
327{
328 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
329 : insert_copy_proxy<Allocator, Iterator>(v)
330 {}
331};
332
333}}} //namespace boost { namespace container { namespace container_detail {
334
335#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
336
337#include <boost/container/detail/value_init.hpp>
338
339namespace boost {
340namespace container {
341namespace container_detail {
342
343#define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
344template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
345struct insert_nonmovable_emplace_proxy##N\
346{\
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;\
350 \
351 explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
352 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
353 \
354 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
355 {\
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);\
358 }\
359 \
360 void copy_n_and_update(Allocator &, Iterator, size_type)\
361 { BOOST_ASSERT(false); }\
362 \
363 protected:\
364 BOOST_MOVE_MREF##N\
365};\
366\
367template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
368struct insert_emplace_proxy_arg##N\
369 : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
370{\
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;\
376 \
377 explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
378 : base_t(BOOST_MOVE_FWD##N){}\
379 \
380 void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
381 {\
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);\
387 BOOST_TRY{\
388 *p = ::boost::move(*vp);\
389 }\
390 BOOST_CATCH(...){\
391 alloc_traits::destroy(a, vp);\
392 BOOST_RETHROW\
393 }\
394 BOOST_CATCH_END\
395 alloc_traits::destroy(a, vp);\
396 }\
397};\
398//
399BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
400#undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
401
402#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
403
404//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
405template<class Allocator, class Iterator>
406struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
407 : public insert_move_proxy<Allocator, Iterator>
408{
409 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
410 : insert_move_proxy<Allocator, Iterator>(v)
411 {}
412};
413
414template<class Allocator, class Iterator>
415struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
416 : public insert_copy_proxy<Allocator, Iterator>
417{
418 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
419 : insert_copy_proxy<Allocator, Iterator>(v)
420 {}
421};
422
423#else //e.g. MSVC10 & MSVC11
424
425//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
426template<class Allocator, class Iterator>
427struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
428 : public insert_move_proxy<Allocator, Iterator>
429{
430 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
431 : insert_move_proxy<Allocator, Iterator>(v)
432 {}
433};
434
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? ;-)
438template<class Allocator, class Iterator>
439struct insert_emplace_proxy_arg1<Allocator, Iterator
440 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
441 >
442 : public insert_copy_proxy<Allocator, Iterator>
443{
444 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
445 : insert_copy_proxy<Allocator, Iterator>(v)
446 {}
447};
448
449template<class Allocator, class Iterator>
450struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
451 : public insert_copy_proxy<Allocator, Iterator>
452{
453 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
454 : insert_copy_proxy<Allocator, Iterator>(v)
455 {}
456};
457
458template<class Allocator, class Iterator>
459struct insert_emplace_proxy_arg1<Allocator, Iterator
460 , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
461 >
462 : public insert_copy_proxy<Allocator, Iterator>
463{
464 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
465 : insert_copy_proxy<Allocator, Iterator>(v)
466 {}
467};
468
469#endif
470
471}}} //namespace boost { namespace container { namespace container_detail {
472
473#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
474
475#include <boost/container/detail/config_end.hpp>
476
477#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
478