You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
385 lines
15 KiB
385 lines
15 KiB
////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// (C) Copyright Ion Gaztanaga 2008-2011. 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 "config_begin.hpp" |
|
#include <boost/container/detail/workaround.hpp> |
|
#include <boost/move/move.hpp> |
|
#include <iterator> //std::iterator_traits |
|
#include <new> //placement new |
|
#include <boost/assert.hpp> |
|
|
|
namespace boost { namespace container { namespace containers_detail { |
|
|
|
//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl |
|
template<class T, class Iterator> |
|
struct advanced_insert_aux_int |
|
{ |
|
typedef typename std::iterator_traits<Iterator>::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<class T, class FwdIt, class Iterator> |
|
struct advanced_insert_aux_proxy |
|
: public advanced_insert_aux_int<T, Iterator> |
|
{ |
|
typedef typename advanced_insert_aux_int<T, Iterator>::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) |
|
{ ::boost::copy_or_move(first_, last_, p); } |
|
|
|
virtual void uninitialized_copy_all_to(Iterator p) |
|
{ ::boost::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::uninitialized_copy_or_move(first_, mid, pos); |
|
first_ = mid; |
|
} |
|
else{ |
|
::boost::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){ |
|
::boost::copy_or_move(first_, mid, pos); |
|
first_ = mid; |
|
} |
|
else{ |
|
::boost::copy_or_move(mid, last_, pos); |
|
last_ = mid; |
|
} |
|
} |
|
|
|
FwdIt first_, last_; |
|
}; |
|
|
|
//This class template will adapt each FwIt types to advanced_insert_aux_int |
|
template<class T, class Iterator, class SizeType> |
|
struct default_construct_aux_proxy |
|
: public advanced_insert_aux_int<T, Iterator> |
|
{ |
|
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; |
|
default_construct_aux_proxy(SizeType count) |
|
: count_(count) |
|
{} |
|
|
|
void uninitialized_copy_impl(Iterator p, const SizeType n) |
|
{ |
|
BOOST_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 |
|
BOOST_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{ |
|
BOOST_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) |
|
{ |
|
BOOST_ASSERT(count_ == 0); |
|
SizeType new_count; |
|
if(first_n){ |
|
new_count = division_count; |
|
} |
|
else{ |
|
BOOST_ASSERT(difference_type(count_)>= division_count); |
|
new_count = count_ - division_count; |
|
} |
|
//This function should never called with a count different to zero |
|
BOOST_ASSERT(new_count == 0); |
|
(void)new_count; |
|
} |
|
|
|
SizeType count_; |
|
}; |
|
|
|
}}} //namespace boost { namespace container { namespace containers_detail { |
|
|
|
#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING |
|
|
|
#include <boost/container/detail/variadic_templates_tools.hpp> |
|
#include <boost/container/detail/stored_ref.hpp> |
|
#include <boost/move/move.hpp> |
|
#include <typeinfo> |
|
//#include <iostream> //For debugging purposes |
|
|
|
namespace boost { |
|
namespace container { |
|
namespace containers_detail { |
|
|
|
//This class template will adapt each FwIt types to advanced_insert_aux_int |
|
template<class T, class Iterator, class ...Args> |
|
struct advanced_insert_aux_emplace |
|
: public advanced_insert_aux_int<T, Iterator> |
|
{ |
|
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; |
|
typedef typename build_number_seq<sizeof...(Args)>::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<int ...IdxPack> |
|
void priv_copy_all_to(const index_tuple<IdxPack...>&, Iterator p) |
|
{ |
|
if(!used_){ |
|
*p = boost::move(T (::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...)); |
|
used_ = true; |
|
} |
|
} |
|
|
|
template<int ...IdxPack> |
|
void priv_uninitialized_copy_all_to(const index_tuple<IdxPack...>&, Iterator p) |
|
{ |
|
if(!used_){ |
|
new(containers_detail::get_pointer(&*p))T(::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...); |
|
used_ = true; |
|
} |
|
} |
|
|
|
template<int ...IdxPack> |
|
void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n) |
|
{ |
|
BOOST_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::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...); |
|
used_ = true; |
|
} |
|
} |
|
} |
|
|
|
template<int ...IdxPack> |
|
void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n) |
|
{ |
|
BOOST_ASSERT(division_count <=1); |
|
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ |
|
if(!used_){ |
|
*p = boost::move(T(::boost::container::containers_detail::stored_ref<Args>::forward(get<IdxPack>(args_))...)); |
|
used_ = true; |
|
} |
|
} |
|
} |
|
tuple<Args&...> args_; |
|
bool used_; |
|
}; |
|
|
|
}}} //namespace boost { namespace container { namespace containers_detail { |
|
|
|
#else //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING |
|
|
|
#include <boost/container/detail/preprocessor.hpp> |
|
#include <boost/container/detail/value_init.hpp> |
|
|
|
namespace boost { |
|
namespace container { |
|
namespace containers_detail { |
|
|
|
//This class template will adapt each FwIt types to advanced_insert_aux_int |
|
template<class T, class Iterator> |
|
struct advanced_insert_aux_emplace |
|
: public advanced_insert_aux_int<T, Iterator> |
|
{ |
|
typedef typename advanced_insert_aux_int<T, Iterator>::difference_type difference_type; |
|
advanced_insert_aux_emplace() |
|
: used_(false) |
|
{} |
|
|
|
~advanced_insert_aux_emplace() |
|
{} |
|
|
|
virtual void copy_all_to(Iterator p) |
|
{ |
|
if(!used_){ |
|
value_init<T>v; |
|
*p = boost::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) |
|
{ |
|
BOOST_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) |
|
{ |
|
BOOST_ASSERT(division_count <=1); |
|
if((first_n && division_count == 1) || (!first_n && division_count == 0)){ |
|
if(!used_){ |
|
value_init<T>v; |
|
*p = boost::move(v.m_t); |
|
used_ = true; |
|
} |
|
} |
|
} |
|
private: |
|
bool used_; |
|
}; |
|
|
|
#define BOOST_PP_LOCAL_MACRO(n) \ |
|
template<class T, class Iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \ |
|
struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \ |
|
: public advanced_insert_aux_int<T, Iterator> \ |
|
{ \ |
|
typedef typename advanced_insert_aux_int<T, Iterator>::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::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) \ |
|
{ \ |
|
BOOST_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) \ |
|
{ \ |
|
BOOST_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::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 <boost/container/detail/config_end.hpp> |
|
|
|
#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP
|
|
|