1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008-2009. 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_CONTAINERS_ADVANCED_INSERT_INT_HPP
12 #define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
13 
14 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
15 #  pragma once
16 #endif
17 
18 #include "config_begin.hpp"
19 #include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
20 #include INCLUDE_BOOST_CONTAINER_MOVE_HPP
21 #include <iterator>  //std::iterator_traits
22 #include <new>       //placement new
23 #include <boost/assert.hpp>
24 
25 namespace boost { namespace container { namespace containers_detail {
26 
27 //This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
28 template<class T, class Iterator>
29 struct advanced_insert_aux_int
30 {
31    typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
32    virtual void copy_all_to(Iterator p) = 0;
33    virtual void uninitialized_copy_all_to(Iterator p) = 0;
34    virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
35    virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
~advanced_insert_aux_intboost::container::containers_detail::advanced_insert_aux_int36    virtual ~advanced_insert_aux_int() {}
37 };
38 
39 //This class template will adapt each FwIt types to advanced_insert_aux_int
40 template<class T, class FwdIt, class Iterator>
41 struct advanced_insert_aux_proxy
42    :  public advanced_insert_aux_int<T, Iterator>
43 {
44    typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
advanced_insert_aux_proxyboost::container::containers_detail::advanced_insert_aux_proxy45    advanced_insert_aux_proxy(FwdIt first, FwdIt last)
46       :  first_(first), last_(last)
47    {}
48 
~advanced_insert_aux_proxyboost::container::containers_detail::advanced_insert_aux_proxy49    virtual ~advanced_insert_aux_proxy()
50    {}
51 
copy_all_toboost::container::containers_detail::advanced_insert_aux_proxy52    virtual void copy_all_to(Iterator p)
53    {  ::BOOST_CONTAINER_MOVE_NAMESPACE::copy_or_move(first_, last_, p);  }
54 
uninitialized_copy_all_toboost::container::containers_detail::advanced_insert_aux_proxy55    virtual void uninitialized_copy_all_to(Iterator p)
56    {  ::BOOST_CONTAINER_MOVE_NAMESPACE::uninitialized_copy_or_move(first_, last_, p);  }
57 
uninitialized_copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_proxy58    virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
59    {
60       FwdIt mid = first_;
61       std::advance(mid, division_count);
62       if(first_n){
63          ::BOOST_CONTAINER_MOVE_NAMESPACE::uninitialized_copy_or_move(first_, mid, pos);
64          first_ = mid;
65       }
66       else{
67          ::BOOST_CONTAINER_MOVE_NAMESPACE::uninitialized_copy_or_move(mid, last_, pos);
68          last_ = mid;
69       }
70    }
71 
copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_proxy72    virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
73    {
74       FwdIt mid = first_;
75       std::advance(mid, division_count);
76       if(first_n){
77          ::BOOST_CONTAINER_MOVE_NAMESPACE::copy_or_move(first_, mid, pos);
78          first_ = mid;
79       }
80       else{
81          ::BOOST_CONTAINER_MOVE_NAMESPACE::copy_or_move(mid, last_, pos);
82          last_ = mid;
83       }
84    }
85 
86    FwdIt first_, last_;
87 };
88 
89 //This class template will adapt each FwIt types to advanced_insert_aux_int
90 template<class T, class Iterator, class SizeType>
91 struct default_construct_aux_proxy
92    :  public advanced_insert_aux_int<T, Iterator>
93 {
94    typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
default_construct_aux_proxyboost::container::containers_detail::default_construct_aux_proxy95    default_construct_aux_proxy(SizeType count)
96       :  count_(count)
97    {}
98 
uninitialized_copy_implboost::container::containers_detail::default_construct_aux_proxy99    void uninitialized_copy_impl(Iterator p, const SizeType n)
100    {
101       BOOST_ASSERT(n <= count_);
102       Iterator orig_p = p;
103       SizeType i = 0;
104       try{
105          for(; i < n; ++i, ++p){
106             new(containers_detail::get_pointer(&*p))T();
107          }
108       }
109       catch(...){
110          while(i--){
111             containers_detail::get_pointer(&*orig_p++)->~T();
112          }
113          throw;
114       }
115       count_ -= n;
116    }
117 
~default_construct_aux_proxyboost::container::containers_detail::default_construct_aux_proxy118    virtual ~default_construct_aux_proxy()
119    {}
120 
copy_all_toboost::container::containers_detail::default_construct_aux_proxy121    virtual void copy_all_to(Iterator)
122    {  //This should never be called with any count
123       BOOST_ASSERT(count_ == 0);
124    }
125 
uninitialized_copy_all_toboost::container::containers_detail::default_construct_aux_proxy126    virtual void uninitialized_copy_all_to(Iterator p)
127    {  this->uninitialized_copy_impl(p, count_); }
128 
uninitialized_copy_some_and_updateboost::container::containers_detail::default_construct_aux_proxy129    virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
130    {
131       SizeType new_count;
132       if(first_n){
133          new_count = division_count;
134       }
135       else{
136          BOOST_ASSERT(difference_type(count_)>= division_count);
137          new_count = count_ - division_count;
138       }
139       this->uninitialized_copy_impl(pos, new_count);
140    }
141 
copy_some_and_updateboost::container::containers_detail::default_construct_aux_proxy142    virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
143    {
144       BOOST_ASSERT(count_ == 0);
145       SizeType new_count;
146       if(first_n){
147          new_count = division_count;
148       }
149       else{
150          BOOST_ASSERT(difference_type(count_)>= division_count);
151          new_count = count_ - division_count;
152       }
153       //This function should never called with a count different to zero
154       BOOST_ASSERT(new_count == 0);
155       (void)new_count;
156    }
157 
158    SizeType count_;
159 };
160 
161 }}}   //namespace boost { namespace container { namespace containers_detail {
162 
163 #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
164 
165 #include INCLUDE_BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
166 #include INCLUDE_BOOST_CONTAINER_DETAIL_STORED_REF_HPP
167 #include INCLUDE_BOOST_CONTAINER_MOVE_HPP
168 #include <typeinfo>
169 //#include <iostream> //For debugging purposes
170 
171 namespace boost {
172 namespace container {
173 namespace containers_detail {
174 
175 //This class template will adapt each FwIt types to advanced_insert_aux_int
176 template<class T, class Iterator, class ...Args>
177 struct advanced_insert_aux_emplace
178    :  public advanced_insert_aux_int<T, Iterator>
179 {
180    typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
181    typedef typename build_number_seq<sizeof...(Args)>::type             index_tuple_t;
182 
advanced_insert_aux_emplaceboost::container::containers_detail::advanced_insert_aux_emplace183    explicit advanced_insert_aux_emplace(Args&&... args)
184       : args_(args...)
185       , used_(false)
186    {}
187 
~advanced_insert_aux_emplaceboost::container::containers_detail::advanced_insert_aux_emplace188    ~advanced_insert_aux_emplace()
189    {}
190 
copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace191    virtual void copy_all_to(Iterator p)
192    {  this->priv_copy_all_to(index_tuple_t(), p);   }
193 
uninitialized_copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace194    virtual void uninitialized_copy_all_to(Iterator p)
195    {  this->priv_uninitialized_copy_all_to(index_tuple_t(), p);   }
196 
uninitialized_copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace197    virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
198    {  this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n);  }
199 
copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace200    virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
201    {  this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n);  }
202 
203    private:
204    template<int ...IdxPack>
priv_copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace205    void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
206    {
207       if(!used_){
208          *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(T (::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...));
209          used_ = true;
210       }
211    }
212 
213    template<int ...IdxPack>
priv_uninitialized_copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace214    void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p)
215    {
216       if(!used_){
217          new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...);
218          used_ = true;
219       }
220    }
221 
222    template<int ...IdxPack>
priv_uninitialized_copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace223    void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
224    {
225       BOOST_ASSERT(division_count <=1);
226       if((first_n && division_count == 1) || (!first_n && division_count == 0)){
227          if(!used_){
228             new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...);
229             used_ = true;
230          }
231       }
232    }
233 
234    template<int ...IdxPack>
priv_copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace235    void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
236    {
237       BOOST_ASSERT(division_count <=1);
238       if((first_n && division_count == 1) || (!first_n && division_count == 0)){
239          if(!used_){
240             *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(T(::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...));
241             used_ = true;
242          }
243       }
244    }
245    tuple<Args&...> args_;
246    bool used_;
247 };
248 
249 }}}   //namespace boost { namespace container { namespace containers_detail {
250 
251 #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
252 
253 #include INCLUDE_BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
254 #include INCLUDE_BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
255 
256 namespace boost {
257 namespace container {
258 namespace containers_detail {
259 
260 //This class template will adapt each FwIt types to advanced_insert_aux_int
261 template<class T, class Iterator>
262 struct advanced_insert_aux_emplace
263    :  public advanced_insert_aux_int<T, Iterator>
264 {
265    typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;
advanced_insert_aux_emplaceboost::container::containers_detail::advanced_insert_aux_emplace266    advanced_insert_aux_emplace()
267       :  used_(false)
268    {}
269 
~advanced_insert_aux_emplaceboost::container::containers_detail::advanced_insert_aux_emplace270    ~advanced_insert_aux_emplace()
271    {}
272 
copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace273    virtual void copy_all_to(Iterator p)
274    {
275       if(!used_){
276          value_init<T>v;
277          *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(v.m_t);
278          used_ = true;
279       }
280    }
281 
uninitialized_copy_all_toboost::container::containers_detail::advanced_insert_aux_emplace282    virtual void uninitialized_copy_all_to(Iterator p)
283    {
284       if(!used_){
285          new(containers_detail::get_pointer(&*p))T();
286          used_ = true;
287       }
288    }
289 
uninitialized_copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace290    virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
291    {
292       BOOST_ASSERT(division_count <=1);
293       if((first_n && division_count == 1) || (!first_n && division_count == 0)){
294          if(!used_){
295             new(containers_detail::get_pointer(&*p))T();
296             used_ = true;
297          }
298       }
299    }
300 
copy_some_and_updateboost::container::containers_detail::advanced_insert_aux_emplace301    virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
302    {
303       BOOST_ASSERT(division_count <=1);
304       if((first_n && division_count == 1) || (!first_n && division_count == 0)){
305          if(!used_){
306             value_init<T>v;
307             *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(v.m_t);
308             used_ = true;
309          }
310       }
311    }
312    private:
313    bool used_;
314 };
315 
316    #define BOOST_PP_LOCAL_MACRO(n)                                                     \
317    template<class T, class Iterator, BOOST_PP_ENUM_PARAMS(n, class P) >                \
318    struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)                \
319       :  public advanced_insert_aux_int<T, Iterator>                                     \
320    {                                                                                   \
321       typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type;  \
322                                                                                        \
323       BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)                    \
324          ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) )          \
325          : used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {}     \
326                                                                                        \
327       virtual void copy_all_to(Iterator p)                                             \
328       {                                                                                \
329          if(!used_){                                                                   \
330             T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));            \
331             *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(v);                                                 \
332             used_ = true;                                                              \
333          }                                                                             \
334       }                                                                                \
335                                                                                        \
336       virtual void uninitialized_copy_all_to(Iterator p)                               \
337       {                                                                                \
338          if(!used_){                                                                   \
339             new(containers_detail::get_pointer(&*p))T                                             \
340                (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));            \
341             used_ = true;                                                              \
342          }                                                                             \
343       }                                                                                \
344                                                                                        \
345       virtual void uninitialized_copy_some_and_update                                  \
346          (Iterator p, difference_type division_count, bool first_n)                    \
347       {                                                                                \
348          BOOST_ASSERT(division_count <=1);                                                   \
349          if((first_n && division_count == 1) || (!first_n && division_count == 0)){    \
350             if(!used_){                                                                \
351                new(containers_detail::get_pointer(&*p))T                                          \
352                   (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));         \
353                used_ = true;                                                           \
354             }                                                                          \
355          }                                                                             \
356       }                                                                                \
357                                                                                        \
358       virtual void copy_some_and_update                                                \
359          (Iterator p, difference_type division_count, bool first_n)                    \
360       {                                                                                \
361          BOOST_ASSERT(division_count <=1);                                                   \
362          if((first_n && division_count == 1) || (!first_n && division_count == 0)){    \
363             if(!used_){                                                                \
364                T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _));         \
365                *p = BOOST_CONTAINER_MOVE_NAMESPACE::move(v);                                              \
366                used_ = true;                                                           \
367             }                                                                          \
368          }                                                                             \
369       }                                                                                \
370                                                                                        \
371       bool used_;                                                                      \
372       BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _)                       \
373    };                                                                                  \
374 //!
375 
376 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
377 #include BOOST_PP_LOCAL_ITERATE()
378 
379 }}}   //namespace boost { namespace container { namespace containers_detail {
380 
381 #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
382 
383 #include INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP
384 
385 #endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
386