////////////////////////////////////////////////////////////////////////////// | |
// | |
// (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 "config_begin.hpp" | |
#include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP | |
#include INCLUDE_BOOST_CONTAINER_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_CONTAINER_MOVE_NAMESPACE::copy_or_move(first_, last_, p); } | |
virtual void uninitialized_copy_all_to(Iterator p) | |
{ ::BOOST_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::uninitialized_copy_or_move(first_, mid, pos); | |
first_ = mid; | |
} | |
else{ | |
::BOOST_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::copy_or_move(first_, mid, pos); | |
first_ = mid; | |
} | |
else{ | |
::BOOST_CONTAINER_MOVE_NAMESPACE::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 INCLUDE_BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP | |
#include INCLUDE_BOOST_CONTAINER_DETAIL_STORED_REF_HPP | |
#include INCLUDE_BOOST_CONTAINER_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_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::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 INCLUDE_BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP | |
#include 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_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::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_CONTAINER_MOVE_NAMESPACE::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 INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP | |
#endif //#ifndef BOOST_CONTAINERS_ADVANCED_INSERT_INT_HPP |