a35279dcf7617be0ff0b892a38af18f1e6b09182
[platform/upstream/boost.git] / boost / container / detail / advanced_insert_int.hpp
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 #if defined(_MSC_VER)
15 #  pragma once
16 #endif
17
18 #include <boost/container/detail/config_begin.hpp>
19 #include <boost/container/detail/workaround.hpp>
20
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>
32
33 namespace boost { namespace container { namespace container_detail {
34
35 template<class A, class FwdIt, class Iterator>
36 struct move_insert_range_proxy
37 {
38    typedef typename allocator_traits<A>::size_type size_type;
39    typedef typename allocator_traits<A>::value_type value_type;
40
41    explicit move_insert_range_proxy(FwdIt first)
42       :  first_(first)
43    {}
44
45    void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
46    {
47       this->first_ = ::boost::container::uninitialized_move_alloc_n_source
48          (a, this->first_, n, p);
49    }
50
51    void copy_n_and_update(A &, Iterator p, size_type n)
52    {
53       this->first_ = ::boost::container::move_n_source(this->first_, n, p);
54    }
55
56    FwdIt first_;
57 };
58
59
60 template<class A, class FwdIt, class Iterator>
61 struct insert_range_proxy
62 {
63    typedef typename allocator_traits<A>::size_type size_type;
64    typedef typename allocator_traits<A>::value_type value_type;
65
66    explicit insert_range_proxy(FwdIt first)
67       :  first_(first)
68    {}
69
70    void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
71    {
72       this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
73    }
74
75    void copy_n_and_update(A &, Iterator p, size_type n)
76    {
77       this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
78    }
79
80    FwdIt first_;
81 };
82
83
84 template<class A, class Iterator>
85 struct insert_n_copies_proxy
86 {
87    typedef typename allocator_traits<A>::size_type size_type;
88    typedef typename allocator_traits<A>::value_type value_type;
89
90    explicit insert_n_copies_proxy(const value_type &v)
91       :  v_(v)
92    {}
93
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);  }
96
97    void copy_n_and_update(A &, Iterator p, size_type n) const
98    {
99            for (; 0 < n; --n, ++p){
100                    *p = v_;
101       }
102    }
103
104    const value_type &v_;
105 };
106
107 template<class A, class Iterator>
108 struct insert_value_initialized_n_proxy
109 {
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;
113
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);  }
116
117    void copy_n_and_update(A &, Iterator, size_type) const
118    {  BOOST_ASSERT(false); }
119 };
120
121 template<class A, class Iterator>
122 struct insert_default_initialized_n_proxy
123 {
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;
127
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);  }
130
131    void copy_n_and_update(A &, Iterator, size_type) const
132    {  BOOST_ASSERT(false); }
133 };
134
135 template<class A, class Iterator>
136 struct insert_copy_proxy
137 {
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;
141
142    explicit insert_copy_proxy(const value_type &v)
143       :  v_(v)
144    {}
145
146    void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
147    {
148       BOOST_ASSERT(n == 1);  (void)n;
149       alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
150    }
151
152    void copy_n_and_update(A &, Iterator p, size_type n) const
153    {
154       BOOST_ASSERT(n == 1);  (void)n;
155       *p =v_;
156    }
157
158    const value_type &v_;
159 };
160
161
162 template<class A, class Iterator>
163 struct insert_move_proxy
164 {
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;
168
169    explicit insert_move_proxy(value_type &v)
170       :  v_(v)
171    {}
172
173    void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
174    {
175       BOOST_ASSERT(n == 1);  (void)n;
176       alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
177    }
178
179    void copy_n_and_update(A &, Iterator p, size_type n) const
180    {
181       BOOST_ASSERT(n == 1);  (void)n;
182       *p = ::boost::move(v_);
183    }
184
185    value_type &v_;
186 };
187
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)
190 {
191    return insert_move_proxy<A, It>(v);
192 }
193
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)
196 {
197    return insert_copy_proxy<A, It>(v);
198 }
199
200 }}}   //namespace boost { namespace container { namespace container_detail {
201
202 #ifdef BOOST_CONTAINER_PERFECT_FORWARDING
203
204 #include <boost/container/detail/variadic_templates_tools.hpp>
205 #include <boost/move/utility_core.hpp>
206 #include <typeinfo>
207 //#include <iostream> //For debugging purposes
208
209 namespace boost {
210 namespace container {
211 namespace container_detail {
212
213 template<class A, class Iterator, class ...Args>
214 struct insert_non_movable_emplace_proxy
215 {
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;
219
220    typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
221
222    explicit insert_non_movable_emplace_proxy(Args&&... args)
223       : args_(args...)
224    {}
225
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);  }
228
229    private:
230    template<int ...IdxPack>
231    void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
232    {
233       BOOST_ASSERT(n == 1); (void)n;
234       alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
235    }
236
237    protected:
238    tuple<Args&...> args_;
239 };
240
241 template<class A, class Iterator, class ...Args>
242 struct insert_emplace_proxy
243    :  public insert_non_movable_emplace_proxy<A, Iterator, Args...>
244 {
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;
250
251    explicit insert_emplace_proxy(Args&&... args)
252       : base_t(::boost::forward<Args>(args)...)
253    {}
254
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);  }
257
258    private:
259
260    template<int ...IdxPack>
261    void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
262    {
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_))...);
268       BOOST_TRY{
269          *p = ::boost::move(*vp);
270       }
271       BOOST_CATCH(...){
272          alloc_traits::destroy(a, vp);
273          BOOST_RETHROW
274       }
275       BOOST_CATCH_END
276       alloc_traits::destroy(a, vp);
277    }
278 };
279
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>
284 {
285    explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v)
286    : insert_move_proxy<A, Iterator>(v)
287    {}
288 };
289
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
296    >
297    : public insert_copy_proxy<A, Iterator>
298 {
299    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
300    : insert_copy_proxy<A, Iterator>(v)
301    {}
302 };
303
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>
307 {
308    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
309    : insert_copy_proxy<A, Iterator>(v)
310    {}
311 };
312
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 &
316    >
317    : public insert_copy_proxy<A, Iterator>
318 {
319    explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
320    : insert_copy_proxy<A, Iterator>(v)
321    {}
322 };
323
324 }}}   //namespace boost { namespace container { namespace container_detail {
325
326 #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
327
328 #include <boost/container/detail/preprocessor.hpp>
329 #include <boost/container/detail/value_init.hpp>
330
331 namespace boost {
332 namespace container {
333 namespace container_detail {
334
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)                        \
338 {                                                                                   \
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;                            \
342                                                                                     \
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, _)     \
346    {}                                                                               \
347                                                                                     \
348    void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)              \
349    {                                                                                \
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, _)            \
354          );                                                                         \
355    }                                                                                \
356                                                                                     \
357    void copy_n_and_update(A &, Iterator, size_type)                                 \
358    {  BOOST_ASSERT(false);   }                                                      \
359                                                                                     \
360    protected:                                                                       \
361    BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _)                           \
362 };                                                                                  \
363                                                                                     \
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) >                        \
368 {                                                                                   \
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;                      \
374                                                                                     \
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, _) )              \
378    {}                                                                               \
379                                                                                     \
380    void copy_n_and_update(A &a, Iterator p, size_type n)                            \
381    {                                                                                \
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, _));          \
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 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
400 #include BOOST_PP_LOCAL_ITERATE()
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 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>
408 {
409    explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v)
410    : insert_move_proxy<A, Iterator>(v)
411    {}
412 };
413
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>
417 {
418    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
419    : insert_copy_proxy<A, 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 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>
429 {
430    explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v)
431    : insert_move_proxy<A, Iterator>(v)
432    {}
433 };
434
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
441    >
442    : public insert_copy_proxy<A, Iterator>
443 {
444    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
445    : insert_copy_proxy<A, Iterator>(v)
446    {}
447 };
448
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>
452 {
453    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
454    : insert_copy_proxy<A, Iterator>(v)
455    {}
456 };
457
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 &
461    >
462    : public insert_copy_proxy<A, Iterator>
463 {
464    explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
465    : insert_copy_proxy<A, Iterator>(v)
466    {}
467 };
468
469 #endif
470
471 }}}   //namespace boost { namespace container { namespace container_detail {
472
473 #endif   //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
474
475 #include <boost/container/detail/config_end.hpp>
476
477 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP