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 
44 namespace boost { namespace container { namespace dtl {
45 
46 template<class Allocator, class FwdIt, class Iterator>
47 struct 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 
move_insert_range_proxyboost::container::dtl::move_insert_range_proxy52    explicit move_insert_range_proxy(FwdIt first)
53       :  first_(first)
54    {}
55 
uninitialized_copy_n_and_updateboost::container::dtl::move_insert_range_proxy56    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 
copy_n_and_updateboost::container::dtl::move_insert_range_proxy62    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 
71 template<class Allocator, class FwdIt, class Iterator>
72 struct 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 
insert_range_proxyboost::container::dtl::insert_range_proxy77    explicit insert_range_proxy(FwdIt first)
78       :  first_(first)
79    {}
80 
uninitialized_copy_n_and_updateboost::container::dtl::insert_range_proxy81    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 
copy_n_and_updateboost::container::dtl::insert_range_proxy86    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 
95 template<class Allocator, class Iterator>
96 struct 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 
insert_n_copies_proxyboost::container::dtl::insert_n_copies_proxy101    explicit insert_n_copies_proxy(const value_type &v)
102       :  v_(v)
103    {}
104 
uninitialized_copy_n_and_updateboost::container::dtl::insert_n_copies_proxy105    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 
copy_n_and_updateboost::container::dtl::insert_n_copies_proxy108    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 
118 template<class Allocator, class Iterator>
119 struct 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 
uninitialized_copy_n_and_updateboost::container::dtl::insert_value_initialized_n_proxy125    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 
copy_n_and_updateboost::container::dtl::insert_value_initialized_n_proxy128    void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
129    {
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);
136       }
137    }
138 };
139 
140 template<class Allocator, class Iterator>
141 struct insert_default_initialized_n_proxy
142 {
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;
146 
uninitialized_copy_n_and_updateboost::container::dtl::insert_default_initialized_n_proxy147    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);  }
149 
copy_n_and_updateboost::container::dtl::insert_default_initialized_n_proxy150    void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
151    {
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);
159          }
160       }
161    }
162 };
163 
164 template<class Allocator, class Iterator>
165 struct insert_copy_proxy
166 {
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;
170 
insert_copy_proxyboost::container::dtl::insert_copy_proxy171    explicit insert_copy_proxy(const value_type &v)
172       :  v_(v)
173    {}
174 
uninitialized_copy_n_and_updateboost::container::dtl::insert_copy_proxy175    void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
176    {
177       BOOST_ASSERT(n == 1);  (void)n;
178       alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
179    }
180 
copy_n_and_updateboost::container::dtl::insert_copy_proxy181    void copy_n_and_update(Allocator &, Iterator p, size_type n) const
182    {
183       BOOST_ASSERT(n == 1);  (void)n;
184       *p = v_;
185    }
186 
187    const value_type &v_;
188 };
189 
190 
191 template<class Allocator, class Iterator>
192 struct insert_move_proxy
193 {
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;
197 
insert_move_proxyboost::container::dtl::insert_move_proxy198    BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
199       :  v_(v)
200    {}
201 
uninitialized_copy_n_and_updateboost::container::dtl::insert_move_proxy202    BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
203    {
204       BOOST_ASSERT(n == 1);  (void)n;
205       alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
206    }
207 
copy_n_and_updateboost::container::dtl::insert_move_proxy208    BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
209    {
210       BOOST_ASSERT(n == 1);  (void)n;
211       *p = ::boost::move(v_);
212    }
213 
214    value_type &v_;
215 };
216 
217 template<class It, class Allocator>
get_insert_value_proxy(BOOST_RV_REF (typename boost::container::iterator_traits<It>::value_type)v)218 insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
219 {
220    return insert_move_proxy<Allocator, It>(v);
221 }
222 
223 template<class It, class Allocator>
get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type & v)224 insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
225 {
226    return insert_copy_proxy<Allocator, It>(v);
227 }
228 
229 }}}   //namespace boost { namespace container { namespace dtl {
230 
231 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
232 
233 #include <boost/container/detail/variadic_templates_tools.hpp>
234 #include <boost/move/utility_core.hpp>
235 
236 namespace boost {
237 namespace container {
238 namespace dtl {
239 
240 template<class Allocator, class Iterator, class ...Args>
241 struct insert_nonmovable_emplace_proxy
242 {
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;
246 
247    typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
248 
insert_nonmovable_emplace_proxyboost::container::dtl::insert_nonmovable_emplace_proxy249    explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
250       : args_(args...)
251    {}
252 
uninitialized_copy_n_and_updateboost::container::dtl::insert_nonmovable_emplace_proxy253    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);  }
255 
256    private:
257    template<std::size_t ...IdxPack>
priv_uninitialized_copy_some_and_updateboost::container::dtl::insert_nonmovable_emplace_proxy258    void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
259    {
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_))... );
262    }
263 
264    protected:
265    tuple<Args&...> args_;
266 };
267 
268 template<class Allocator, class Iterator, class ...Args>
269 struct insert_emplace_proxy
270    :  public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
271 {
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;
277 
insert_emplace_proxyboost::container::dtl::insert_emplace_proxy278    explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
279       : base_t(::boost::forward<Args>(args)...)
280    {}
281 
copy_n_and_updateboost::container::dtl::insert_emplace_proxy282    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);  }
284 
285    private:
286 
287    template<std::size_t ...IdxPack>
priv_copy_some_and_updateboost::container::dtl::insert_emplace_proxy288    void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
289    {
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_))...);
295       BOOST_TRY{
296          *p = ::boost::move(*vp);
297       }
298       BOOST_CATCH(...){
299          alloc_traits::destroy(a, vp);
300          BOOST_RETHROW
301       }
302       BOOST_CATCH_END
303       alloc_traits::destroy(a, vp);
304    }
305 };
306 
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>
311 {
insert_emplace_proxyboost::container::dtl::insert_emplace_proxy312    explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
313    : insert_move_proxy<Allocator, Iterator>(v)
314    {}
315 };
316 
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
323    >
324    : public insert_copy_proxy<Allocator, Iterator>
325 {
insert_emplace_proxyboost::container::dtl::insert_emplace_proxy326    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
327    : insert_copy_proxy<Allocator, Iterator>(v)
328    {}
329 };
330 
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>
334 {
insert_emplace_proxyboost::container::dtl::insert_emplace_proxy335    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
336    : insert_copy_proxy<Allocator, Iterator>(v)
337    {}
338 };
339 
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 &
343    >
344    : public insert_copy_proxy<Allocator, Iterator>
345 {
insert_emplace_proxyboost::container::dtl::insert_emplace_proxy346    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
347    : insert_copy_proxy<Allocator, Iterator>(v)
348    {}
349 };
350 
351 }}}   //namespace boost { namespace container { namespace dtl {
352 
353 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
354 
355 #include <boost/container/detail/value_init.hpp>
356 
357 namespace boost {
358 namespace container {
359 namespace dtl {
360 
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\
364 {\
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;\
368    \
369    explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
370       BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
371    \
372    void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
373    {\
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);\
376    }\
377    \
378    void copy_n_and_update(Allocator &, Iterator, size_type)\
379    {  BOOST_ASSERT(false);   }\
380    \
381    protected:\
382    BOOST_MOVE_MREF##N\
383 };\
384 \
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 >\
388 {\
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;\
394    \
395    explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
396       : base_t(BOOST_MOVE_FWD##N){}\
397    \
398    void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
399    {\
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);\
405       BOOST_TRY{\
406          *p = ::boost::move(*vp);\
407       }\
408       BOOST_CATCH(...){\
409          alloc_traits::destroy(a, vp);\
410          BOOST_RETHROW\
411       }\
412       BOOST_CATCH_END\
413       alloc_traits::destroy(a, vp);\
414    }\
415 };\
416 //
417 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
418 #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
419 
420 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
421 
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>
426 {
insert_emplace_proxy_arg1boost::container::dtl::insert_emplace_proxy_arg1427    explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
428    : insert_move_proxy<Allocator, Iterator>(v)
429    {}
430 };
431 
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>
435 {
insert_emplace_proxy_arg1boost::container::dtl::insert_emplace_proxy_arg1436    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
437    : insert_copy_proxy<Allocator, Iterator>(v)
438    {}
439 };
440 
441 #else //e.g. MSVC10 & MSVC11
442 
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>
447 {
448    explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
449    : insert_move_proxy<Allocator, Iterator>(v)
450    {}
451 };
452 
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
459    >
460    : public insert_copy_proxy<Allocator, Iterator>
461 {
462    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
463    : insert_copy_proxy<Allocator, Iterator>(v)
464    {}
465 };
466 
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>
470 {
471    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
472    : insert_copy_proxy<Allocator, Iterator>(v)
473    {}
474 };
475 
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 &
479    >
480    : public insert_copy_proxy<Allocator, Iterator>
481 {
482    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
483    : insert_copy_proxy<Allocator, Iterator>(v)
484    {}
485 };
486 
487 #endif
488 
489 }}}   //namespace boost { namespace container { namespace dtl {
490 
491 #endif   // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
492 
493 #include <boost/container/detail/config_end.hpp>
494 
495 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
496