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 container_detail {
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::container_detail::move_insert_range_proxy52    explicit move_insert_range_proxy(FwdIt first)
53       :  first_(first)
54    {}
55 
uninitialized_copy_n_and_updateboost::container::container_detail::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::container_detail::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::container_detail::insert_range_proxy77    explicit insert_range_proxy(FwdIt first)
78       :  first_(first)
79    {}
80 
uninitialized_copy_n_and_updateboost::container::container_detail::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::container_detail::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::container_detail::insert_n_copies_proxy101    explicit insert_n_copies_proxy(const value_type &v)
102       :  v_(v)
103    {}
104 
uninitialized_copy_n_and_updateboost::container::container_detail::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::container_detail::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::container_detail::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::container_detail::insert_value_initialized_n_proxy128    void copy_n_and_update(Allocator &, Iterator, size_type) const
129    {  BOOST_ASSERT(false); }
130 };
131 
132 template<class Allocator, class Iterator>
133 struct 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 
uninitialized_copy_n_and_updateboost::container::container_detail::insert_default_initialized_n_proxy139    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 
copy_n_and_updateboost::container::container_detail::insert_default_initialized_n_proxy142    void copy_n_and_update(Allocator &, Iterator, size_type) const
143    {  BOOST_ASSERT(false); }
144 };
145 
146 template<class Allocator, class Iterator>
147 struct 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 
insert_copy_proxyboost::container::container_detail::insert_copy_proxy153    explicit insert_copy_proxy(const value_type &v)
154       :  v_(v)
155    {}
156 
uninitialized_copy_n_and_updateboost::container::container_detail::insert_copy_proxy157    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 
copy_n_and_updateboost::container::container_detail::insert_copy_proxy163    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 
173 template<class Allocator, class Iterator>
174 struct 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 
insert_move_proxyboost::container::container_detail::insert_move_proxy180    explicit insert_move_proxy(value_type &v)
181       :  v_(v)
182    {}
183 
uninitialized_copy_n_and_updateboost::container::container_detail::insert_move_proxy184    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 
copy_n_and_updateboost::container::container_detail::insert_move_proxy190    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 
199 template<class It, class Allocator>
get_insert_value_proxy(BOOST_RV_REF (typename boost::container::iterator_traits<It>::value_type)v)200 insert_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 
205 template<class It, class Allocator>
get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type & v)206 insert_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 
218 namespace boost {
219 namespace container {
220 namespace container_detail {
221 
222 template<class Allocator, class Iterator, class ...Args>
223 struct 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 
insert_nonmovable_emplace_proxyboost::container::container_detail::insert_nonmovable_emplace_proxy231    explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
232       : args_(args...)
233    {}
234 
uninitialized_copy_n_and_updateboost::container::container_detail::insert_nonmovable_emplace_proxy235    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>
priv_uninitialized_copy_some_and_updateboost::container::container_detail::insert_nonmovable_emplace_proxy240    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 
250 template<class Allocator, class Iterator, class ...Args>
251 struct 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 
insert_emplace_proxyboost::container::container_detail::insert_emplace_proxy260    explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
261       : base_t(::boost::forward<Args>(args)...)
262    {}
263 
copy_n_and_updateboost::container::container_detail::insert_emplace_proxy264    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>
priv_copy_some_and_updateboost::container::container_detail::insert_emplace_proxy270    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
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>
293 {
insert_emplace_proxyboost::container::container_detail::insert_emplace_proxy294    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? ;-)
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
305    >
306    : public insert_copy_proxy<Allocator, Iterator>
307 {
insert_emplace_proxyboost::container::container_detail::insert_emplace_proxy308    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
309    : insert_copy_proxy<Allocator, Iterator>(v)
310    {}
311 };
312 
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>
316 {
insert_emplace_proxyboost::container::container_detail::insert_emplace_proxy317    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
318    : insert_copy_proxy<Allocator, Iterator>(v)
319    {}
320 };
321 
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 &
325    >
326    : public insert_copy_proxy<Allocator, Iterator>
327 {
insert_emplace_proxyboost::container::container_detail::insert_emplace_proxy328    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 
339 namespace boost {
340 namespace container {
341 namespace container_detail {
342 
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\
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 \
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 >\
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 //
399 BOOST_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
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>
408 {
insert_emplace_proxy_arg1boost::container::container_detail::insert_emplace_proxy_arg1409    explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
410    : insert_move_proxy<Allocator, Iterator>(v)
411    {}
412 };
413 
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>
417 {
insert_emplace_proxy_arg1boost::container::container_detail::insert_emplace_proxy_arg1418    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
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>
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? ;-)
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
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 
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>
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 
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 &
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