////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP #define BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include #include #include #include //std::iterator_traits #include //std::copy, std::uninitialized_copy #include //placement new #include namespace boost { namespace container { namespace containers_detail { //This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl template struct advanced_insert_aux_int { typedef typename std::iterator_traits::difference_type difference_type; virtual void copy_all_to(Iterator p) = 0; virtual void uninitialized_copy_all_to(Iterator p) = 0; virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0; virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0; virtual ~advanced_insert_aux_int() {} }; //This class template will adapt each FwIt types to advanced_insert_aux_int template struct advanced_insert_aux_proxy : public advanced_insert_aux_int { typedef typename advanced_insert_aux_int::difference_type difference_type; advanced_insert_aux_proxy(FwdIt first, FwdIt last) : first_(first), last_(last) {} virtual ~advanced_insert_aux_proxy() {} virtual void copy_all_to(Iterator p) { std::copy(first_, last_, p); } virtual void uninitialized_copy_all_to(Iterator p) { ::boost::interprocess::uninitialized_copy_or_move(first_, last_, p); } virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { FwdIt mid = first_; std::advance(mid, division_count); if(first_n){ ::boost::interprocess::uninitialized_copy_or_move(first_, mid, pos); first_ = mid; } else{ ::boost::interprocess::uninitialized_copy_or_move(mid, last_, pos); last_ = mid; } } virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { FwdIt mid = first_; std::advance(mid, division_count); if(first_n){ std::copy(first_, mid, pos); first_ = mid; } else{ std::copy(mid, last_, pos); last_ = mid; } } FwdIt first_, last_; }; //This class template will adapt each FwIt types to advanced_insert_aux_int template struct default_construct_aux_proxy : public advanced_insert_aux_int { typedef typename advanced_insert_aux_int::difference_type difference_type; default_construct_aux_proxy(SizeType count) : count_(count) {} void uninitialized_copy_impl(Iterator p, const SizeType n) { assert(n <= count_); Iterator orig_p = p; SizeType i = 0; try{ for(; i < n; ++i, ++p){ new(containers_detail::get_pointer(&*p))T(); } } catch(...){ while(i--){ containers_detail::get_pointer(&*orig_p++)->~T(); } throw; } count_ -= n; } virtual ~default_construct_aux_proxy() {} virtual void copy_all_to(Iterator) { //This should never be called with any count assert(count_ == 0); } virtual void uninitialized_copy_all_to(Iterator p) { this->uninitialized_copy_impl(p, count_); } virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n) { SizeType new_count; if(first_n){ new_count = division_count; } else{ assert(difference_type(count_)>= division_count); new_count = count_ - division_count; } this->uninitialized_copy_impl(pos, new_count); } virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n) { assert(count_ == 0); SizeType new_count; if(first_n){ new_count = division_count; } else{ assert(difference_type(count_)>= division_count); new_count = count_ - division_count; } //This function should never called with a count different to zero assert(new_count == 0); (void)new_count; } SizeType count_; }; }}} //namespace boost { namespace container { namespace containers_detail { #ifdef BOOST_CONTAINERS_PERFECT_FORWARDING #include #include #include //#include //For debugging purposes namespace boost { namespace container { namespace containers_detail { //This class template will adapt each FwIt types to advanced_insert_aux_int template struct advanced_insert_aux_emplace : public advanced_insert_aux_int { typedef typename advanced_insert_aux_int::difference_type difference_type; typedef typename build_number_seq::type index_tuple_t; explicit advanced_insert_aux_emplace(Args&&... args) : args_(args...), used_(false) {} ~advanced_insert_aux_emplace() {} virtual void copy_all_to(Iterator p) { this->priv_copy_all_to(index_tuple_t(), p); } virtual void uninitialized_copy_all_to(Iterator p) { this->priv_uninitialized_copy_all_to(index_tuple_t(), p); } virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); } virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); } private: template void priv_copy_all_to(const index_tuple&, Iterator p) { if(!used_){ *p = boost::interprocess::move(T (boost::interprocess::forward(get(args_))...)); used_ = true; } } template void priv_uninitialized_copy_all_to(const index_tuple&, Iterator p) { if(!used_){ new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward(get(args_))...); used_ = true; } } template void priv_uninitialized_copy_some_and_update(const index_tuple&, Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ new(containers_detail::get_pointer(&*p))T(boost::interprocess::forward(get(args_))...); used_ = true; } } } template void priv_copy_some_and_update(const index_tuple&, Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ *p = boost::interprocess::move(T(boost::interprocess::forward(get(args_))...)); used_ = true; } } } tuple args_; bool used_; }; }}} //namespace boost { namespace container { namespace containers_detail { #else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING #include #include namespace boost { namespace container { namespace containers_detail { //This class template will adapt each FwIt types to advanced_insert_aux_int template struct advanced_insert_aux_emplace : public advanced_insert_aux_int { typedef typename advanced_insert_aux_int::difference_type difference_type; advanced_insert_aux_emplace() : used_(false) {} ~advanced_insert_aux_emplace() {} virtual void copy_all_to(Iterator p) { if(!used_){ value_initv; *p = boost::interprocess::move(v.m_t); used_ = true; } } virtual void uninitialized_copy_all_to(Iterator p) { if(!used_){ new(containers_detail::get_pointer(&*p))T(); used_ = true; } } virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ new(containers_detail::get_pointer(&*p))T(); used_ = true; } } } virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n) { assert(division_count <=1); if((first_n && division_count == 1) || (!first_n && division_count == 0)){ if(!used_){ value_initv; *p = boost::interprocess::move(v.m_t); used_ = true; } } } private: bool used_; }; #define BOOST_PP_LOCAL_MACRO(n) \ template \ struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ : public advanced_insert_aux_int \ { \ typedef typename advanced_insert_aux_int::difference_type difference_type; \ \ BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ ( BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _) ) \ : used_(false), BOOST_PP_ENUM(n, BOOST_CONTAINERS_AUX_PARAM_INIT, _) {} \ \ virtual void copy_all_to(Iterator p) \ { \ if(!used_){ \ T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ *p = boost::interprocess::move(v); \ used_ = true; \ } \ } \ \ virtual void uninitialized_copy_all_to(Iterator p) \ { \ if(!used_){ \ new(containers_detail::get_pointer(&*p))T \ (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ used_ = true; \ } \ } \ \ virtual void uninitialized_copy_some_and_update \ (Iterator p, difference_type division_count, bool first_n) \ { \ assert(division_count <=1); \ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \ if(!used_){ \ new(containers_detail::get_pointer(&*p))T \ (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ used_ = true; \ } \ } \ } \ \ virtual void copy_some_and_update \ (Iterator p, difference_type division_count, bool first_n) \ { \ assert(division_count <=1); \ if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \ if(!used_){ \ T v(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_MEMBER_FORWARD, _)); \ *p = boost::interprocess::move(v); \ used_ = true; \ } \ } \ } \ \ bool used_; \ BOOST_PP_REPEAT(n, BOOST_CONTAINERS_AUX_PARAM_DEFINE, _) \ }; \ //! #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() }}} //namespace boost { namespace container { namespace containers_detail { #endif //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING #include #endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP