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