Implemented LWG Issue #149 (range insertion now returns an iterator) & cleaned up insertion code in most containers

[SVN r80348]
This commit is contained in:
Ion Gaztañaga
2012-09-01 11:01:03 +00:00
parent 011f1fb181
commit 3c256c2282
29 changed files with 1659 additions and 1476 deletions

View File

@@ -617,7 +617,7 @@ use [*Boost.Container]? There are several reasons for that:
[section:release_notes_boost_1_52_00 Boost 1.52 Release]
* Fixed bugs
[@https://svn.boost.org/trac/boost/ticket/6606 #6606],
[@https://svn.boost.org/trac/boost/ticket/6615 #6615],
[@https://svn.boost.org/trac/boost/ticket/7139 #7139],
[@https://svn.boost.org/trac/boost/ticket/7215 #7215],
[@https://svn.boost.org/trac/boost/ticket/7232 #7232],
@@ -641,11 +641,11 @@ use [*Boost.Container]? There are several reasons for that:
* Added Scoped Allocator Model support.
* Fixed bugs
[@https://svn.boost.org/trac/boost/ticket/6606 #6606],
[@https://svn.boost.org/trac/boost/ticket/6533 #6533],
[@https://svn.boost.org/trac/boost/ticket/6536 #6536],
[@https://svn.boost.org/trac/boost/ticket/6566 #6566],
[@https://svn.boost.org/trac/boost/ticket/6575 #6575],
[@https://svn.boost.org/trac/boost/ticket/6615 #6615],
[endsect]

View File

@@ -943,14 +943,18 @@ class deque : protected deque_base<T, A>
//! throws or T's constructor taking an dereferenced InIt throws.
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InpIt>
deque(InpIt first, InpIt last, const allocator_type& a = allocator_type())
template <class InIt>
deque(InIt first, InIt last, const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
>::type * = 0
#endif
)
: Base(a)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_initialize_dispatch(first, last, Result());
typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_range_initialize(first, last, ItCat());
}
//! <b>Effects</b>: Destroys the deque. All stored values are destroyed
@@ -1043,23 +1047,61 @@ class deque : protected deque_base<T, A>
//!
//! <b>Complexity</b>: Linear to n.
void assign(size_type n, const T& val)
{ this->priv_fill_assign(n, val); }
{
typedef constant_iterator<value_type, difference_type> c_it;
this->assign(c_it(val, n), c_it());
}
//! <b>Effects</b>: Assigns the the range [first, last) to *this.
//!
//! <b>Throws</b>: If memory allocation throws or
//! T's constructor from dereferencing InpIt throws.
//! T's constructor from dereferencing InIt throws.
//!
//! <b>Complexity</b>: Linear to n.
template <class InpIt>
void assign(InpIt first, InpIt last)
template <class InIt>
void assign(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first){
*cur = *first;
}
if (first == last){
this->erase(cur, cend());
}
else{
this->insert(cend(), first, last);
}
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
void assign(FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
)
{
const size_type len = std::distance(first, last);
if (len > size()) {
FwdIt mid = first;
std::advance(mid, size());
boost::copy_or_move(first, mid, begin());
this->insert(cend(), mid, last);
}
else{
this->erase(boost::copy_or_move(first, last, begin()), cend());
}
}
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts a copy of x at the end of the deque.
//!
@@ -1142,6 +1184,8 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert a copy of x before position.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1152,6 +1196,8 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert a new element before position with mx's resources.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1165,29 +1211,63 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert n copies of x before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or pos if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
void insert(const_iterator pos, size_type n, const value_type& x)
{ this->priv_fill_insert(pos, n, x); }
iterator insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
return this->insert(pos, c_it(x, n), c_it());
}
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws or T's copy constructor throws.
//! dereferenced InIt throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InpIt>
void insert(const_iterator pos, InpIt first, InpIt last)
template <class InIt>
iterator insert(const_iterator pos, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_dispatch(pos, first, last, Result());
size_type n = 0;
iterator it(pos);
for(;first != last; ++first, ++n){
it = this->emplace(it, *first);
++it;
}
it -= n;
return it;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator p, FwdIt first, FwdIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
#endif
)
{
container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
#endif
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
@@ -1257,11 +1337,9 @@ class deque : protected deque_base<T, A>
return (this->end()-1);
}
else{
size_type n = p - this->cbegin();
typedef container_detail::advanced_insert_aux_emplace<A, iterator, Args...> type;
type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
this->priv_insert_aux_impl(p, 1, proxy);
return iterator(this->begin() + n);
return this->priv_insert_aux_impl(p, 1, proxy);
}
}
@@ -1320,12 +1398,10 @@ class deque : protected deque_base<T, A>
return (this->end()-1); \
} \
else{ \
size_type pos_num = p - this->cbegin(); \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
this->priv_insert_aux_impl(p, 1, proxy); \
return iterator(this->begin() + pos_num); \
return this->priv_insert_aux_impl(p, 1, proxy); \
} \
} \
//!
@@ -1361,7 +1437,7 @@ class deque : protected deque_base<T, A>
if (new_size < len)
this->priv_erase_last_n(len - new_size);
else{
size_type n = new_size - this->size();
const size_type n = new_size - this->size();
container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
priv_insert_back_aux_impl(n, proxy);
}
@@ -1500,9 +1576,7 @@ class deque : protected deque_base<T, A>
return (end()-1);
}
else {
size_type n = position - cbegin();
this->priv_insert_aux(position, size_type(1), x);
return iterator(this->begin() + n);
return this->insert(position, size_type(1), x);
}
}
@@ -1517,10 +1591,7 @@ class deque : protected deque_base<T, A>
return(end()-1);
}
else {
//Just call more general insert(pos, size, value) and return iterator
size_type n = position - begin();
this->priv_insert_aux(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
return iterator(this->begin() + n);
return this->insert(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
}
}
@@ -1532,7 +1603,7 @@ class deque : protected deque_base<T, A>
this->priv_push_front_simple_commit();
}
else{
this->priv_insert_aux(cbegin(), size_type(1), t);
this->insert(cbegin(), size_type(1), t);
}
}
@@ -1544,7 +1615,7 @@ class deque : protected deque_base<T, A>
this->priv_push_front_simple_commit();
}
else{
this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
this->insert(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
}
@@ -1556,7 +1627,7 @@ class deque : protected deque_base<T, A>
this->priv_push_back_simple_commit();
}
else{
this->priv_insert_aux(cend(), size_type(1), t);
this->insert(cend(), size_type(1), t);
}
}
@@ -1568,7 +1639,7 @@ class deque : protected deque_base<T, A>
this->priv_push_back_simple_commit();
}
else{
this->priv_insert_aux(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
this->insert(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
}
@@ -1600,50 +1671,6 @@ class deque : protected deque_base<T, A>
void priv_push_front_simple_commit()
{ --this->members_.m_start.m_cur; }
template <class InpIt>
void priv_insert_aux(const_iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
{
iterator it(pos);
for(;first != last; ++first){
it = this->emplace(it, *first);
++it;
}
}
template <class FwdIt>
void priv_insert_aux(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
{ this->priv_insert_aux(pos, first, last); }
// assign(), a generalized assignment member function. Two
// versions: one that takes a count, and one that takes a range.
// The range version is a member template, so we dispatch on whether
// or not the type is an integer.
void priv_fill_assign(size_type n, const T& val)
{
if (n > size()) {
std::fill(begin(), end(), val);
this->insert(cend(), n - size(), val);
}
else {
this->erase(cbegin() + n, cend());
std::fill(begin(), end(), val);
}
}
template <class Integer>
void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
{
this->priv_initialize_map(n);
this->priv_fill_initialize(x);
}
template <class InpIt>
void priv_initialize_dispatch(InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_range_initialize(first, last, ItCat());
}
void priv_destroy_range(iterator p, iterator p2)
{
for(;p != p2; ++p){
@@ -1664,71 +1691,10 @@ class deque : protected deque_base<T, A>
}
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
{ this->priv_fill_assign((size_type) n, (value_type)val); }
template <class InpIt>
void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_assign_aux(first, last, ItCat());
}
template <class InpIt>
void priv_assign_aux(InpIt first, InpIt last, std::input_iterator_tag)
{
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first)
*cur = *first;
if (first == last)
this->erase(cur, cend());
else
this->insert(cend(), first, last);
}
template <class FwdIt>
void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
{
size_type len = std::distance(first, last);
if (len > size()) {
FwdIt mid = first;
std::advance(mid, size());
boost::copy_or_move(first, mid, begin());
this->insert(cend(), mid, last);
}
else
this->erase(boost::copy_or_move(first, last, begin()), cend());
}
template <class Integer>
void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, container_detail::true_)
{ this->priv_fill_insert(pos, (size_type) n, (value_type)x); }
template <class InpIt>
void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_insert_aux(pos, first, last, ItCat());
}
void priv_insert_aux(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
this->priv_insert_aux(pos, c_it(x, n), c_it());
}
//Just forward all operations to priv_insert_aux_impl
template <class FwdIt>
void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
{
container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
void priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
{
iterator pos(p);
const size_type pos_n = p - this->cbegin();
if(!this->members_.m_map){
this->priv_initialize_map(0);
pos = this->begin();
@@ -1782,9 +1748,10 @@ class deque : protected deque_base<T, A>
interf.copy_remaining_to(pos);
}
}
return this->begin() + pos_n;
}
void priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1794,9 +1761,10 @@ class deque : protected deque_base<T, A>
iterator old_finish = this->members_.m_finish;
interf.uninitialized_copy_some_and_update(old_finish, n, true);
this->members_.m_finish = new_finish;
return iterator(this->members_.m_finish - n);
}
void priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1805,13 +1773,13 @@ class deque : protected deque_base<T, A>
iterator new_start = this->priv_reserve_elements_at_front(n);
interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true);
this->members_.m_start = new_start;
return new_start;
}
void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
this->insert(pos, c_it(x, n), c_it());
return this->insert(pos, c_it(x, n), c_it());
}
// Precondition: this->members_.m_start and this->members_.m_finish have already been initialized,
@@ -1834,13 +1802,13 @@ class deque : protected deque_base<T, A>
BOOST_CATCH_END
}
template <class InpIt>
void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag)
template <class InIt>
void priv_range_initialize(InIt first, InIt last, std::input_iterator_tag)
{
this->priv_initialize_map(0);
BOOST_TRY {
for ( ; first != last; ++first)
this->push_back(*first);
this->emplace_back(*first);
}
BOOST_CATCH(...){
this->clear();

View File

@@ -173,7 +173,6 @@ struct default_construct_aux_proxy
#ifdef BOOST_CONTAINER_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
@@ -227,8 +226,7 @@ struct advanced_insert_aux_non_movable_emplace
if(!this->used_){
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::container::container_detail::
stored_ref<Args>::forward(get<IdxPack>(this->args_))...
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
this->used_ = true;
}
@@ -241,8 +239,7 @@ struct advanced_insert_aux_non_movable_emplace
if(!this->used_){
alloc_traits::construct( this->a_
, container_detail::to_raw_pointer(&*p)
, ::boost::container::container_detail::
stored_ref<Args>::forward(get<IdxPack>(this->args_))...
, ::boost::forward<Args>(get<IdxPack>(this->args_))...
);
this->used_ = true;
}
@@ -288,7 +285,7 @@ struct advanced_insert_aux_emplace
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(this->a_, vp,
::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
::boost::forward<Args>(get<IdxPack>(this->args_))...);
scoped_destructor<A> d(this->a_, vp);
*p = ::boost::move(*vp);
d.release();
@@ -305,7 +302,7 @@ struct advanced_insert_aux_emplace
aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
alloc_traits::construct(this->a_, vp,
::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
::boost::forward<Args>(get<IdxPack>(this->args_))...);
try {
*p = ::boost::move(*vp);
} catch (...) {
@@ -413,7 +410,7 @@ struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)
alloc_traits::construct(this->a_, vp \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
scoped_destructor<A> d(this->a_, vp); \
*p = ::boost::move(*vp); \
*p = ::boost::move(*vp); \
d.release(); \
this->used_ = true; \
} \
@@ -430,7 +427,7 @@ struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)
alloc_traits::construct(this->a_, vp \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
scoped_destructor<A> d(this->a_, vp); \
*p = ::boost::move(*vp); \
*p = ::boost::move(*vp); \
d.release(); \
this->used_ = true; \
} \

View File

@@ -34,6 +34,30 @@
namespace boost {
namespace container {
template<class It>
struct is_default_construct_iterator
{
static const bool value = false;
};
template<class U, class D>
struct is_default_construct_iterator<default_construct_iterator<U, D> >
{
static const bool value = true;
};
template<class It>
struct is_emplace_iterator
{
static const bool value = false;
};
template<class U, class EF, class D>
struct is_emplace_iterator<emplace_iterator<U, EF, D> >
{
static const bool value = true;
};
template<class A, class T, class InpIt>
inline void construct_in_place(A &a, T* dest, InpIt source)
{ boost::container::allocator_traits<A>::construct(a, dest, *source); }

View File

@@ -214,6 +214,21 @@ class flat_tree
: m_data(comp, a)
{ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
template <class InputIterator>
flat_tree( bool unique_insertion
, InputIterator first, InputIterator last
, const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
: m_data(comp, a)
{
if(unique_insertion){
this->insert_unique(first, last);
}
else{
this->insert_equal(first, last);
}
}
~flat_tree()
{ }
@@ -290,9 +305,9 @@ class flat_tree
std::pair<iterator,bool> insert_unique(const value_type& val)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, val);
ret.first = this->priv_insert_commit(data, val);
}
return ret;
}
@@ -300,9 +315,9 @@ class flat_tree
std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, boost::move(val));
ret.first = this->priv_insert_commit(data, boost::move(val));
}
return ret;
}
@@ -324,9 +339,9 @@ class flat_tree
iterator insert_unique(const_iterator pos, const value_type& val)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, val, data);
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(pos, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, val);
ret.first = this->priv_insert_commit(data, val);
}
return ret.first;
}
@@ -334,9 +349,9 @@ class flat_tree
iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) mval)
{
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(pos, mval, data);
if(ret.second){
ret.first = priv_insert_commit(data, boost::move(mval));
ret.first = this->priv_insert_commit(data, boost::move(mval));
}
return ret.first;
}
@@ -345,45 +360,164 @@ class flat_tree
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, val, data);
return priv_insert_commit(data, val);
return this->priv_insert_commit(data, val);
}
iterator insert_equal(const_iterator pos, BOOST_RV_REF(value_type) mval)
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, mval, data);
return priv_insert_commit(data, boost::move(mval));
return this->priv_insert_commit(data, boost::move(mval));
}
template <class InIt>
void insert_unique(InIt first, InIt last)
{ this->priv_insert_unique_loop(first, last); }
template <class InIt>
void insert_equal(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{ this->priv_insert_equal_loop(first, last); }
template <class InIt>
void insert_equal(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
for ( ; first != last; ++first)
this->insert_unique(*first);
const size_type len = static_cast<size_type>(std::distance(first, last));
this->reserve(this->size()+len);
this->priv_insert_equal_loop(first, last);
}
//Ordered
template <class InIt>
void insert_equal(ordered_range_t, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{ this->priv_insert_equal_loop_ordered(first, last); }
template <class FwdIt>
void insert_equal(ordered_range_t, FwdIt first, FwdIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_forward_iterator<FwdIt>::value
>::type * = 0
#endif
)
{
const size_type len = static_cast<size_type>(std::distance(first, last));
this->reserve(this->size()+len);
this->priv_insert_equal_loop_ordered(first, last);
}
template <class BidirIt>
void insert_equal(ordered_range_t, BidirIt first, BidirIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_input_iterator<BidirIt>::value &&
!container_detail::is_forward_iterator<BidirIt>::value
>::type * = 0
#endif
)
{
size_type len = static_cast<size_type>(std::distance(first, last));
const size_type BurstSize = 16;
size_type positions[BurstSize];
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
//Loop in burst sizes
while(len){
const size_type burst = len < BurstSize ? len : BurstSize;
const const_iterator cend(this->cend());
len -= burst;
for(size_type i = 0; i != burst; ++i){
//Get the insertion position for each key
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, cend, KeyOfValue()(*first));
positions[i] = static_cast<size_type>(pos - beg);
++first;
}
//Insert all in a single step in the precalculated positions
this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
//Next search position updated
pos += burst;
}
}
template <class InIt>
void insert_equal(InIt first, InIt last)
{
typedef typename
std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_insert_equal(first, last, ItCat());
}
void insert_unique(ordered_unique_range_t, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_input_iterator<InIt>::value ||
container_detail::is_forward_iterator<InIt>::value
>::type * = 0
#endif
)
{ this->priv_insert_unique_loop_hint(first, last); }
template <class InIt>
void insert_equal(ordered_range_t, InIt first, InIt last)
template <class BidirIt>
void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !(container_detail::is_input_iterator<BidirIt>::value ||
container_detail::is_forward_iterator<BidirIt>::value)
>::type * = 0
#endif
)
{
typedef typename
std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_insert_equal(ordered_range_t(), first, last, ItCat());
}
size_type len = static_cast<size_type>(std::distance(first, last));
const size_type BurstSize = 16;
size_type positions[BurstSize];
size_type skips[BurstSize];
template <class InIt>
void insert_unique(ordered_unique_range_t, InIt first, InIt last)
{
typedef typename
std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_insert_unique(ordered_unique_range_t(), first, last, ItCat());
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
const value_compare &value_comp = this->m_data;
//Loop in burst sizes
while(len){
skips[0u] = 0u;
const size_type burst = len < BurstSize ? len : BurstSize;
size_type unique_burst = 0u;
const const_iterator cend(this->cend());
while(unique_burst < burst && len > 0){
//Get the insertion position for each key
const value_type & val = *first++;
--len;
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, cend, KeyOfValue()(val));
//Check if already present
if(pos != cend && !value_comp(*pos, val)){
++skips[unique_burst];
continue;
}
//If not present, calculate position
positions[unique_burst] = static_cast<size_type>(pos - beg);
if(++unique_burst < burst)
skips[unique_burst] = 0u;
}
//Insert all in a single step in the precalculated positions
this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first);
//Next search position updated
pos += unique_burst;
}
}
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -398,9 +532,9 @@ class flat_tree
value_destructor<stored_allocator_type> d(a, val);
insert_commit_data data;
std::pair<iterator,bool> ret =
priv_insert_unique_prepare(val, data);
this->priv_insert_unique_prepare(val, data);
if(ret.second){
ret.first = priv_insert_commit(data, boost::move(val));
ret.first = this->priv_insert_commit(data, boost::move(val));
}
return ret;
}
@@ -414,9 +548,9 @@ class flat_tree
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
insert_commit_data data;
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(hint, val, data);
if(ret.second){
ret.first = priv_insert_commit(data, boost::move(val));
ret.first = this->priv_insert_commit(data, boost::move(val));
}
return ret.first;
}
@@ -444,7 +578,7 @@ class flat_tree
value_destructor<stored_allocator_type> d(a, val);
insert_commit_data data;
this->priv_insert_equal_prepare(hint, val, data);
iterator i = priv_insert_commit(data, boost::move(val));
iterator i = this->priv_insert_commit(data, boost::move(val));
return i;
}
@@ -462,9 +596,9 @@ class flat_tree
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, boost::move(val)); \
ret.first = this->priv_insert_commit(data, boost::move(val)); \
} \
return ret; \
} \
@@ -480,9 +614,9 @@ class flat_tree
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
insert_commit_data data; \
std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
std::pair<iterator,bool> ret = this->priv_insert_unique_prepare(hint, val, data); \
if(ret.second){ \
ret.first = priv_insert_commit(data, boost::move(val)); \
ret.first = this->priv_insert_commit(data, boost::move(val)); \
} \
return ret.first; \
} \
@@ -513,7 +647,7 @@ class flat_tree
value_destructor<stored_allocator_type> d(a, val); \
insert_commit_data data; \
this->priv_insert_equal_prepare(hint, val, data); \
iterator i = priv_insert_commit(data, boost::move(val)); \
iterator i = this->priv_insert_commit(data, boost::move(val)); \
return i; \
} \
@@ -653,7 +787,7 @@ class flat_tree
std::pair<iterator,bool> priv_insert_unique_prepare
(const value_type& val, insert_commit_data &commit_data)
{ return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
{ return this->priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
std::pair<iterator,bool> priv_insert_unique_prepare
(const_iterator pos, const value_type& val, insert_commit_data &commit_data)
@@ -794,102 +928,38 @@ class flat_tree
return std::pair<RanIt, RanIt>(first, first);
}
template <class BidirIt>
void priv_insert_equal(ordered_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
template<class InIt>
void priv_insert_equal_loop(InIt first, InIt last)
{
size_type len = static_cast<size_type>(std::distance(first, last));
const size_type BurstSize = 16;
size_type positions[BurstSize];
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
//Loop in burst sizes
while(len){
const size_type burst = len < BurstSize ? len : BurstSize;
const const_iterator cend(this->cend());
len -= burst;
for(size_type i = 0; i != burst; ++i){
//Get the insertion position for each key
pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, cend, KeyOfValue()(*first));
positions[i] = static_cast<size_type>(pos - beg);
++first;
}
//Insert all in a single step in the precalculated positions
this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
//Next search position updated
pos += burst;
}
}
template <class BidirIt>
void priv_insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
{
size_type len = static_cast<size_type>(std::distance(first, last));
const size_type BurstSize = 16;
size_type positions[BurstSize];
size_type skips[BurstSize];
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
const const_iterator beg(this->cbegin());
const_iterator pos(beg);
const value_compare &value_comp = this->m_data;
//Loop in burst sizes
while(len){
skips[0u] = 0u;
const size_type burst = len < BurstSize ? len : BurstSize;
size_type unique_burst = 0u;
const const_iterator cend(this->cend());
while(unique_burst < burst && len > 0){
//Get the insertion position for each key
const value_type & val = *first++;
--len;
pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, cend, KeyOfValue()(val));
//Check if already present
if(pos != cend && !value_comp(*pos, val)){
++skips[unique_burst];
continue;
}
//If not present, calculate position
positions[unique_burst] = static_cast<size_type>(pos - beg);
if(++unique_burst < burst)
skips[unique_burst] = 0u;
}
//Insert all in a single step in the precalculated positions
this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first);
//Next search position updated
pos += unique_burst;
}
}
/*
template <class FwdIt>
void priv_insert_equal_forward(ordered_range_t, FwdIt first, FwdIt last, std::forward_iterator_tag)
{ this->priv_insert_equal(first, last, std::forward_iterator_tag()); }
*/
template <class InIt>
void priv_insert_equal(ordered_range_t, InIt first, InIt last, std::input_iterator_tag)
{ this->priv_insert_equal(first, last, std::input_iterator_tag()); }
template <class InIt>
void priv_insert_unique(ordered_unique_range_t, InIt first, InIt last, std::input_iterator_tag)
{ this->priv_insert_unique(first, last, std::input_iterator_tag()); }
/*
template <class FwdIt>
void priv_insert_equal_forward(FwdIt first, FwdIt last, std::forward_iterator_tag)
{
const size_type len = static_cast<size_type>(std::distance(first, last));
this->reserve(this->size()+len);
this->priv_insert_equal(first, last, std::input_iterator_tag());
}
*/
template <class InIt>
void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag)
{
for ( ; first != last; ++first)
for ( ; first != last; ++first){
this->insert_equal(*first);
}
}
template<class InIt>
void priv_insert_equal_loop_ordered(InIt first, InIt last)
{
const_iterator pos(this->cend());
for ( ; first != last; ++first){
pos = this->insert_equal(pos, *first);
}
}
template<class InIt>
void priv_insert_unique_loop(InIt first, InIt last)
{
for ( ; first != last; ++first){
this->insert_unique(*first);
}
}
template<class InIt>
void priv_insert_unique_loop_ordered(InIt first, InIt last)
{
const_iterator pos(this->cend());
for ( ; first != last; ++first){
pos = this->insert_unique(pos, *first);
}
}
};

View File

@@ -22,10 +22,10 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/move/move.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/type_traits.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
#include <boost/container/detail/stored_ref.hpp>
#else
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -222,14 +222,12 @@ class default_construct_iterator
default_construct_iterator operator-(Difference off) const
{ return *this + (-off); }
const T& operator*() const
{ return dereference(); }
const T* operator->() const
{ return &(dereference()); }
const T& operator[] (Difference n) const
{ return dereference(); }
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
//const T& operator*() const;
//const T& operator[](difference_type) const;
//const T* operator->() const;
private:
Difference m_num;
@@ -445,14 +443,12 @@ class emplace_iterator
this_type operator-(difference_type off) const
{ return *this + (-off); }
const T& operator*() const
{ return dereference(); }
const T& operator[](difference_type) const
{ return dereference(); }
const T* operator->() const
{ return &(dereference()); }
//This pseudo-iterator's dereference operations have no sense since value is not
//constructed until ::boost::container::construct_in_place is called.
//So comment them to catch bad uses
//const T& operator*() const;
//const T& operator[](difference_type) const;
//const T* operator->() const;
template<class A>
void construct_in_place(A &a, T* ptr)
@@ -506,8 +502,7 @@ struct emplace_functor
void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<A>::construct
(a, ptr, container_detail::stored_ref<Args>::forward
(container_detail::get<IdxPack>(args_))...);
(a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
}
container_detail::tuple<Args&...> args_;
@@ -539,6 +534,59 @@ struct emplace_functor
#endif
namespace container_detail {
template<class T>
struct has_iterator_category
{
template <typename X>
static char test(int, typename X::iterator_category*);
template <typename X>
static int test(int, ...);
static const bool value = (1 == sizeof(test<T>(0, 0)));
};
template<class T, bool = has_iterator_category<T>::value >
struct is_input_iterator
{
static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
};
template<class T>
struct is_input_iterator<T, false>
{
static const bool value = false;
};
template<class T, bool = has_iterator_category<T>::value >
struct is_forward_iterator
{
static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
};
template<class T>
struct is_forward_iterator<T, false>
{
static const bool value = false;
};
template<class T, bool = has_iterator_category<T>::value >
struct is_bidirectional_iterator
{
static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
};
template<class T>
struct is_bidirectional_iterator<T, false>
{
static const bool value = false;
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {

View File

@@ -16,11 +16,6 @@
#endif
#include <boost/container/detail/config_begin.hpp>
#ifndef BOOST_NO_RVALUE_REFERENCES
#include <boost/container/detail/stored_ref.hpp>
#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
#include <boost/container/detail/workaround.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -78,19 +73,10 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#ifndef BOOST_NO_RVALUE_REFERENCES
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (static_cast<BOOST_PP_CAT(P, n)>( BOOST_PP_CAT(p, n) )) \
#else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
//!
#endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
#else //BOOST_NO_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
@@ -102,8 +88,68 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
namespace boost {
namespace container {
namespace container_detail {
template<class T>
struct ref_holder;
template<class T>
struct ref_holder<T &>
{
ref_holder(T &t)
: t_(t)
{}
T &t_;
T & get() { return t_; }
};
template<class T>
struct ref_holder<const T>
{
ref_holder(const T &t)
: t_(t)
{}
const T &t_;
const T & get() { return t_; }
};
template<class T>
struct ref_holder<const T &&>
{
ref_holder(const T &t)
: t_(t)
{}
const T &t_;
const T & get() { return t_; }
};
template<class T>
struct ref_holder
{
ref_holder(T &&t)
: t_(t)
{}
T &t_;
T && get() { return ::boost::move(t_); }
};
template<class T>
struct ref_holder<T &&>
{
ref_holder(T &&t)
: t(t)
{}
T &t;
T && get() { return ::boost::move(t_); }
};
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
::boost::container::container_detail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
//!
#else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
@@ -123,8 +169,7 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(this->m_p, n) ) \
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
//!
#else //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)

View File

@@ -1,92 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2008-2012. 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_CONTAINER_DETAIL_STORED_REF_HPP
#define BOOST_CONTAINER_DETAIL_STORED_REF_HPP
#include "config_begin.hpp"
#include <boost/container/detail/workaround.hpp>
#ifndef BOOST_NO_RVALUE_REFERENCES
namespace boost{
namespace container{
namespace container_detail{
template<class T>
struct stored_ref
{
static T && forward(T &t)
#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
{ return t; }
#else
{ return boost::move(t); }
#endif
};
template<class T>
struct stored_ref<const T>
{
static const T && forward(const T &t)
#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
{ return t; }
#else
{ return static_cast<const T&&>(t); }
#endif
};
template<class T>
struct stored_ref<T&&>
{
static T && forward(T &t)
#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
{ return t; }
#else
{ return boost::move(t); }
#endif
};
template<class T>
struct stored_ref<const T&&>
{
static const T && forward(const T &t)
#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
{ return t; }
#else
{ return static_cast<const T &&>(t); }
#endif
};
template<class T>
struct stored_ref<const T&>
{
static const T & forward(const T &t)
{ return t; }
};
template<class T>
struct stored_ref<T&>
{
static T & forward(T &t)
{ return t; }
};
} //namespace container_detail{
} //namespace container{
} //namespace boost{
#else
#error "This header can be included only for compiler with rvalue references"
#endif //BOOST_NO_RVALUE_REFERENCES
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_STORED_REF_HPP

View File

@@ -476,21 +476,77 @@ class rbtree
{}
template <class InputIterator>
rbtree(InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a, bool unique_insertion)
rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_input_iterator<InputIterator>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
>::type * = 0
#endif
)
: AllocHolder(a, comp)
{
typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
priv_create_and_insert_nodes(first, last, unique_insertion, alloc_version(), ItCat());
if(unique_insertion){
this->insert_unique(first, last);
}
else{
this->insert_equal(first, last);
}
}
template <class InputIterator>
rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
const allocator_type& a
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !(container_detail::is_input_iterator<InputIterator>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value)
>::type * = 0
#endif
)
: AllocHolder(a, comp)
{
if(unique_insertion){
this->insert_unique(first, last);
}
else{
//Optimized allocation and construction
this->allocate_many_and_construct
(first, std::distance(first, last), insert_equal_end_hint_functor(this->icont()));
}
}
template <class InputIterator>
rbtree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type())
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< container_detail::is_input_iterator<InputIterator>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
>::type * = 0
#endif
)
: AllocHolder(a, comp)
{
typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
priv_create_and_insert_ordered_nodes(first, last, alloc_version(), ItCat());
this->insert_equal(first, last);
}
template <class InputIterator>
rbtree( ordered_range_t, InputIterator first, InputIterator last
, const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !(container_detail::is_input_iterator<InputIterator>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value)
>::type * = 0
#endif
)
: AllocHolder(a, comp)
{
//Optimized allocation and construction
this->allocate_many_and_construct
(first, std::distance(first, last), push_back_functor(this->icont()));
}
rbtree(const rbtree& x)
@@ -943,14 +999,14 @@ class rbtree
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
std::pair<iterator,iterator> equal_range(const key_type& k)
{
{
std::pair<iiterator, iiterator> ret =
this->icont().equal_range(k, KeyNodeCompare(value_comp()));
return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
{
{
std::pair<iiterator, iiterator> ret =
this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp()));
return std::pair<const_iterator,const_iterator>
@@ -958,108 +1014,39 @@ class rbtree
}
private:
//Iterator range version
template<class InpIterator>
void priv_create_and_insert_nodes
(InpIterator beg, InpIterator end, bool unique, allocator_v1, std::input_iterator_tag)
{
if(unique){
for (; beg != end; ++beg){
this->insert_unique(*beg);
}
}
else{
for (; beg != end; ++beg){
this->insert_equal(*beg);
}
}
}
template<class InpIterator>
void priv_create_and_insert_nodes
(InpIterator beg, InpIterator end, bool unique, allocator_v2, std::input_iterator_tag)
{ //Just forward to the default one
priv_create_and_insert_nodes(beg, end, unique, allocator_v1(), std::input_iterator_tag());
}
class insert_equal_end_hint_functor;
friend class insert_equal_end_hint_functor;
class insertion_functor;
friend class insertion_functor;
class insertion_functor
class insert_equal_end_hint_functor
{
Icont &icont_;
const iconst_iterator cend_;
public:
insertion_functor(Icont &icont)
: icont_(icont)
insert_equal_end_hint_functor(Icont &icont)
: icont_(icont), cend_(this->icont_.cend())
{}
void operator()(Node &n)
{ this->icont_.insert_equal(this->icont_.cend(), n); }
{ this->icont_.insert_equal(cend_, n); }
};
class push_back_functor;
friend class push_back_functor;
template<class FwdIterator>
void priv_create_and_insert_nodes
(FwdIterator beg, FwdIterator end, bool unique, allocator_v2, std::forward_iterator_tag)
{
if(beg != end){
if(unique){
priv_create_and_insert_nodes(beg, end, unique, allocator_v2(), std::input_iterator_tag());
}
else{
//Optimized allocation and construction
this->allocate_many_and_construct
(beg, std::distance(beg, end), insertion_functor(this->icont()));
}
}
}
//Iterator range version
template<class InpIterator>
void priv_create_and_insert_ordered_nodes
(InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
{
const_iterator cend_n(this->cend());
for (; beg != end; ++beg){
this->insert_before(cend_n, *beg);
}
}
template<class InpIterator>
void priv_create_and_insert_ordered_nodes
(InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
{ //Just forward to the default one
priv_create_and_insert_ordered_nodes(beg, end, allocator_v1(), std::input_iterator_tag());
}
class back_insertion_functor;
friend class back_insertion_functor;
class back_insertion_functor
class push_back_functor
{
Icont &icont_;
public:
back_insertion_functor(Icont &icont)
push_back_functor(Icont &icont)
: icont_(icont)
{}
void operator()(Node &n)
{ this->icont_.push_back(n); }
};
template<class FwdIterator>
void priv_create_and_insert_ordered_nodes
(FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
{
if(beg != end){
//Optimized allocation and construction
this->allocate_many_and_construct
(beg, std::distance(beg, end), back_insertion_functor(this->icont()));
}
}
};
template <class Key, class Value, class KeyOfValue,

View File

@@ -190,8 +190,8 @@ class flat_map
template <class InputIterator>
flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{ m_flat_tree.insert_unique(first, last); }
: m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [first ,last). This function
@@ -988,8 +988,8 @@ class flat_multimap
flat_multimap(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
{ m_flat_tree.insert_equal(first, last); }
: m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a))
{}
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last). This function

View File

@@ -125,8 +125,8 @@ class flat_set
flat_set(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, a)
{ m_flat_tree.insert_unique(first, last); }
: m_flat_tree(true, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty flat_set using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [first ,last). This function
@@ -777,8 +777,8 @@ class flat_multiset
flat_multiset(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_flat_tree(comp, a)
{ m_flat_tree.insert_equal(first, last); }
: m_flat_tree(false, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last ). This function

View File

@@ -660,18 +660,8 @@ class list
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size, const T& x)
{
const_iterator iend = this->cend();
size_type len = this->size();
if(len > new_size){
size_type to_erase = len - new_size;
while(to_erase--){
--iend;
}
this->erase(iend, this->cend());
}
else{
this->priv_create_and_insert_nodes(iend, new_size - len, x);
if(!priv_try_shrink(new_size)){
this->insert(this->cend(), new_size - this->size(), x);
}
}
@@ -683,29 +673,9 @@ class list
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size)
{
const_iterator iend = this->end();
size_type len = this->size();
if(len > new_size){
size_type to_erase = len - new_size;
const_iterator ifirst;
if(to_erase < len/2u){
ifirst = iend;
while(to_erase--){
--ifirst;
}
}
else{
ifirst = this->begin();
size_type to_skip = len - to_erase;
while(to_skip--){
++ifirst;
}
}
this->erase(ifirst, iend);
}
else{
this->priv_create_and_insert_nodes(this->cend(), new_size - len);
if(!priv_try_shrink(new_size)){
typedef default_construct_iterator<value_type, difference_type> default_iterator;
this->insert(this->cend(), default_iterator(new_size - this->size()), default_iterator());
}
}
@@ -776,33 +746,76 @@ class list
//!
//! <b>Effects</b>: Inserts n copies of x before p.
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
void insert(const_iterator p, size_type n, const T& x)
{ this->priv_create_and_insert_nodes(p, n, x); }
iterator insert(const_iterator p, size_type n, const T& x)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->insert(p, cvalue_iterator(x, n), cvalue_iterator());
}
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before p.
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InpIt>
void insert(const_iterator p, InpIt first, InpIt last)
iterator insert(const_iterator p, InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InpIt, size_type>::value
&& (container_detail::is_input_iterator<InpIt>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
)
>::type * = 0
#endif
)
{
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_dispatch(p, first, last, Result());
const typename Icont::iterator ipos(p.get());
iterator ret_it(ipos);
if(first != last){
ret_it = iterator(this->icont().insert(ipos, *this->create_node_from_it(first)));
++first;
}
for (; first != last; ++first){
this->icont().insert(ipos, *this->create_node_from_it(first));
}
return ret_it;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator p, FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !(container_detail::is_input_iterator<FwdIt>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
)
>::type * = 0
)
{
//Optimized allocation and construction
insertion_functor func(this->icont(), p.get());
this->allocate_many_and_construct(first, std::distance(first, last), func);
return iterator(func.inserted_first());
}
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Requires</b>: position must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of x before position.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time.
@@ -812,6 +825,8 @@ class list
//!
//! <b>Effects</b>: Insert a new element before position with mx's resources.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
@@ -919,7 +934,10 @@ class list
//!
//! <b>Complexity</b>: Linear to n.
void assign(size_type n, const T& val)
{ this->priv_fill_assign(n, val); }
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->assign(cvalue_iterator(val, n), cvalue_iterator());
}
//! <b>Effects</b>: Assigns the the range [first, last) to *this.
//!
@@ -928,11 +946,23 @@ class list
//!
//! <b>Complexity</b>: Linear to n.
template <class InpIt>
void assign(InpIt first, InpIt last)
void assign(InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InpIt, size_type>::value
>::type * = 0
#endif
)
{
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
iterator first1 = this->begin();
const iterator last1 = this->end();
for ( ; first1 != last1 && first != last; ++first1, ++first)
*first1 = *first;
if (first == last)
this->erase(first1, last1);
else{
this->insert(last1, first, last);
}
}
//! <b>Requires</b>: p must point to an element contained
@@ -1151,6 +1181,34 @@ class list
/// @cond
private:
bool priv_try_shrink(size_type new_size)
{
const size_type len = this->size();
if(len > new_size){
const const_iterator iend = this->cend();
size_type to_erase = len - new_size;
const_iterator ifirst;
if(to_erase < len/2u){
ifirst = iend;
while(to_erase--){
--ifirst;
}
}
else{
ifirst = this->cbegin();
size_type to_skip = len - to_erase;
while(to_skip--){
++ifirst;
}
}
this->erase(ifirst, iend);
return true;
}
else{
return false;
}
}
iterator priv_insert(const_iterator p, const T &x)
{
NodePtr tmp = AllocHolder::create_node(x);
@@ -1175,117 +1233,39 @@ class list
void priv_push_front (BOOST_RV_REF(T) x)
{ this->insert(this->cbegin(), boost::move(x)); }
//Iterator range version
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator pos, InpIterator beg, InpIterator end)
{
typedef typename std::iterator_traits<InpIterator>::iterator_category ItCat;
priv_create_and_insert_nodes(pos, beg, end, alloc_version(), ItCat());
}
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator pos, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
{
for (; beg != end; ++beg){
this->icont().insert(pos.get(), *this->create_node_from_it(beg));
}
}
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator pos, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
{ //Just forward to the default one
priv_create_and_insert_nodes(pos, beg, end, allocator_v1(), std::input_iterator_tag());
}
class insertion_functor;
friend class insertion_functor;
class insertion_functor
{
Icont &icont_;
typename Icont::const_iterator pos_;
typedef typename Icont::iterator iiterator;
typedef typename Icont::const_iterator iconst_iterator;
const iconst_iterator pos_;
iiterator ret_;
bool first_;
public:
insertion_functor(Icont &icont, typename Icont::const_iterator pos)
: icont_(icont), pos_(pos)
: icont_(icont), pos_(pos), ret_(pos.unconst()), first_(true)
{}
void operator()(Node &n)
{ this->icont_.insert(pos_, n); }
{
if(first_){
ret_ = this->icont_.insert(pos_, n);
first_ = false;
}
else{
this->icont_.insert(pos_, n);
}
}
iiterator inserted_first() const
{ return ret_; }
};
template<class FwdIterator>
void priv_create_and_insert_nodes
(const_iterator pos, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
{
if(beg != end){
//Optimized allocation and construction
this->allocate_many_and_construct
(beg, std::distance(beg, end), insertion_functor(this->icont(), pos.get()));
}
}
//Default constructed version
void priv_create_and_insert_nodes(const_iterator pos, size_type n)
{
typedef default_construct_iterator<value_type, difference_type> default_iterator;
this->priv_create_and_insert_nodes(pos, default_iterator(n), default_iterator());
}
//Copy constructed version
void priv_create_and_insert_nodes(const_iterator pos, size_type n, const T& x)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
this->priv_create_and_insert_nodes(pos, cvalue_iterator(x, n), cvalue_iterator());
}
//Dispatch to detect iterator range or integer overloads
template <class InputIter>
void priv_insert_dispatch(const_iterator p,
InputIter first, InputIter last,
container_detail::false_)
{ this->priv_create_and_insert_nodes(p, first, last); }
template<class Integer>
void priv_insert_dispatch(const_iterator p, Integer n, Integer x, container_detail::true_)
{ this->insert(p, (size_type)n, x); }
void priv_fill_assign(size_type n, const T& val)
{
iterator i = this->begin(), iend = this->end();
for ( ; i != iend && n > 0; ++i, --n)
*i = val;
if (n > 0){
this->priv_create_and_insert_nodes(this->cend(), n, val);
}
else{
this->erase(i, cend());
}
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
{ this->priv_fill_assign((size_type) n, (T) val); }
template <class InputIter>
void priv_assign_dispatch(InputIter first2, InputIter last2, container_detail::false_)
{
iterator first1 = this->begin();
iterator last1 = this->end();
for ( ; first1 != last1 && first2 != last2; ++first1, ++first2)
*first1 = *first2;
if (first2 == last2)
this->erase(first1, last1);
else{
this->priv_create_and_insert_nodes(last1, first2, last2);
}
}
//Functors for member algorithm defaults
struct value_less
{

View File

@@ -155,7 +155,7 @@ class map
template <class InputIterator>
map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_tree(first, last, comp, a, true)
: m_tree(true, first, last, comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
@@ -902,7 +902,7 @@ class multimap
multimap(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_tree(first, last, comp, a, false)
: m_tree(false, first, last, comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));

View File

@@ -118,7 +118,7 @@ class set
template <class InputIterator>
set(InputIterator first, InputIterator last, const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_tree(first, last, comp, a, true)
: m_tree(true, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object and
@@ -705,7 +705,7 @@ class multiset
multiset(InputIterator first, InputIterator last,
const Pred& comp = Pred(),
const allocator_type& a = allocator_type())
: m_tree(first, last, comp, a, false)
: m_tree(false, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and

View File

@@ -23,6 +23,7 @@
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
@@ -336,7 +337,7 @@ class slist
//! <b>Complexity</b>: Linear to n.
explicit slist(size_type n, const value_type& x, const allocator_type& a = allocator_type())
: AllocHolder(a)
{ this->priv_create_and_insert_nodes(this->before_begin(), n, x); }
{ this->insert_after(this->cbefore_begin(), n, x); }
//! <b>Effects</b>: Constructs a list that will use a copy of allocator a
//! and inserts a copy of the range [first, last) in the list.
@@ -349,7 +350,7 @@ class slist
slist(InpIt first, InpIt last,
const allocator_type& a = allocator_type())
: AllocHolder(a)
{ this->insert_after(this->before_begin(), first, last); }
{ this->insert_after(this->cbefore_begin(), first, last); }
//! <b>Effects</b>: Copy constructs a list.
//!
@@ -360,7 +361,7 @@ class slist
//! <b>Complexity</b>: Linear to the elements x contains.
slist(const slist& x)
: AllocHolder(x)
{ this->insert_after(this->before_begin(), x.begin(), x.end()); }
{ this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
//!
@@ -380,7 +381,7 @@ class slist
//! <b>Complexity</b>: Linear to the elements x contains.
slist(const slist& x, const allocator_type &a)
: AllocHolder(a)
{ this->insert_after(this->before_begin(), x.begin(), x.end()); }
{ this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor using the specified allocator.
//! Moves x's resources to *this.
@@ -485,7 +486,10 @@ class slist
//!
//! <b>Complexity</b>: Linear to n.
void assign(size_type n, const T& val)
{ this->priv_fill_assign(n, val); }
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->assign(cvalue_iterator(val, n), cvalue_iterator());
}
//! <b>Effects</b>: Assigns the range [first, last) to *this.
//!
@@ -494,11 +498,27 @@ class slist
//!
//! <b>Complexity</b>: Linear to n.
template <class InpIt>
void assign(InpIt first, InpIt last)
void assign(InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InpIt, size_type>::value
>::type * = 0
#endif
)
{
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
iterator end_n(this->end());
iterator prev(this->before_begin());
iterator node(this->begin());
while (node != end_n && first != last){
*node = *first;
prev = node;
++node;
++first;
}
if (first != last)
this->insert_after(prev, first, last);
else
this->erase_after(prev, end_n);
}
//! <b>Effects</b>: Returns an iterator to the first element contained in the list.
@@ -535,7 +555,7 @@ class slist
//! <b>Effects</b>: Returns a non-dereferenceable iterator that,
//! when incremented, yields begin(). This iterator may be used
//! as the argument toinsert_after, erase_after, etc.
//! as the argument to insert_after, erase_after, etc.
//!
//! <b>Throws</b>: Nothing.
//!
@@ -545,7 +565,7 @@ class slist
//! <b>Effects</b>: Returns a non-dereferenceable const_iterator
//! that, when incremented, yields begin(). This iterator may be used
//! as the argument toinsert_after, erase_after, etc.
//! as the argument to insert_after, erase_after, etc.
//!
//! <b>Throws</b>: Nothing.
//!
@@ -571,7 +591,7 @@ class slist
//! <b>Effects</b>: Returns a non-dereferenceable const_iterator
//! that, when incremented, yields begin(). This iterator may be used
//! as the argument toinsert_after, erase_after, etc.
//! as the argument to insert_after, erase_after, etc.
//!
//! <b>Throws</b>: Nothing.
//!
@@ -734,20 +754,28 @@ class slist
//!
//! <b>Effects</b>: Inserts n copies of x after prev_pos.
//!
//! <b>Returns</b>: an iterator to the last inserted element or prev_pos if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//!
//! <b>Complexity</b>: Linear to n.
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
void insert_after(const_iterator prev_pos, size_type n, const value_type& x)
{ this->priv_create_and_insert_nodes(prev_pos, n, x); }
iterator insert_after(const_iterator prev_pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->insert_after(prev_pos, cvalue_iterator(x, n), cvalue_iterator());
}
//! <b>Requires</b>: prev_pos must be a valid iterator of *this.
//!
//! <b>Effects</b>: Inserts the range pointed by [first, last)
//! after the p prev_pos.
//!
//! <b>Returns</b>: an iterator to the last inserted element or prev_pos if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws.
//!
@@ -755,18 +783,49 @@ class slist
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
template <class InIter>
void insert_after(const_iterator prev_pos, InIter first, InIter last)
template <class InpIt>
iterator insert_after(const_iterator prev_pos, InpIt first, InpIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InpIt, size_type>::value
&& (container_detail::is_input_iterator<InpIt>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
)
>::type * = 0
#endif
)
{
const bool aux_boolean = container_detail::is_convertible<InIter, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_after_range_dispatch(prev_pos, first, last, Result());
iterator ret_it(prev_pos.get());
for (; first != last; ++first){
ret_it = iterator(this->icont().insert_after(ret_it.get(), *this->create_node_from_it(first)));
}
return ret_it;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert_after(const_iterator prev, FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !(container_detail::is_input_iterator<FwdIt>::value
|| container_detail::is_same<alloc_version, allocator_v1>::value
)
>::type * = 0
)
{
//Optimized allocation and construction
insertion_functor func(this->icont(), prev.get());
this->allocate_many_and_construct(first, std::distance(first, last), func);
return iterator(func.inserted_first());
}
#endif
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of x before p.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to the elements before p.
@@ -787,6 +846,8 @@ class slist
//!
//! <b>Effects</b>: Insert a new element before p with mx's resources.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Linear to the elements before p.
@@ -797,24 +858,36 @@ class slist
//!
//! <b>Effects</b>: Inserts n copies of x before p.
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if n == 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n plus linear to the elements before p.
void insert(const_iterator p, size_type n, const value_type& x)
{ return this->insert_after(previous(p), n, x); }
iterator insert(const_iterator p, size_type n, const value_type& x)
{
const_iterator prev(this->previous(p));
this->insert_after(prev, n, x);
return ++iterator(prev.get());
}
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before p.
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last) plus
//! linear to the elements before p.
template <class InIter>
void insert(const_iterator p, InIter first, InIter last)
{ return this->insert_after(previous(p), first, last); }
iterator insert(const_iterator p, InIter first, InIter last)
{
const_iterator prev(this->previous(p));
this->insert_after(prev, first, last);
return ++iterator(prev.get());
}
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -948,15 +1021,10 @@ class slist
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size, const T& x)
{
typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next;
while (++(cur_next = cur) != end_n && new_size > 0){
--new_size;
cur = cur_next;
const_iterator last_pos;
if(!priv_try_shrink(new_size, last_pos)){
this->insert_after(last_pos, new_size, x);
}
if (cur_next != end_n)
this->erase_after(const_iterator(cur), const_iterator(end_n));
else
this->insert_after(const_iterator(cur), new_size, x);
}
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -967,19 +1035,10 @@ class slist
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type new_size)
{
typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next;
size_type len = this->size();
size_type left = new_size;
while (++(cur_next = cur) != end_n && left > 0){
--left;
cur = cur_next;
}
if (cur_next != end_n){
this->erase_after(const_iterator(cur), const_iterator(end_n));
}
else{
this->priv_create_and_insert_nodes(const_iterator(cur), new_size - len);
const_iterator last_pos;
if(!priv_try_shrink(new_size, last_pos)){
typedef default_construct_iterator<value_type, difference_type> default_iterator;
this->insert_after(last_pos, default_iterator(new_size - this->size()), default_iterator());
}
}
@@ -1279,6 +1338,24 @@ class slist
/// @cond
private:
bool priv_try_shrink(size_type new_size, const_iterator &last_pos)
{
typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next;
while (++(cur_next = cur) != end_n && new_size > 0){
--new_size;
cur = cur_next;
}
last_pos = const_iterator(cur);
if (cur_next != end_n){
this->erase_after(last_pos, const_iterator(end_n));
return true;
}
else{
return false;
}
}
iterator priv_insert(const_iterator p, const value_type& x)
{ return this->insert_after(previous(p), x); }
@@ -1288,129 +1365,31 @@ class slist
void priv_push_front(const value_type &x)
{ this->icont().push_front(*this->create_node(x)); }
//Iterator range version
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator prev, InpIterator beg, InpIterator end)
{
typedef typename std::iterator_traits<InpIterator>::iterator_category ItCat;
priv_create_and_insert_nodes(prev, beg, end, alloc_version(), ItCat());
}
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator prev, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
{
for (; beg != end; ++beg){
this->icont().insert_after(prev.get(), *this->create_node_from_it(beg));
++prev;
}
}
template<class InpIterator>
void priv_create_and_insert_nodes
(const_iterator prev, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
{ //Just forward to the default one
priv_create_and_insert_nodes(prev, beg, end, allocator_v1(), std::input_iterator_tag());
}
class insertion_functor;
friend class insertion_functor;
class insertion_functor
{
Icont &icont_;
typename Icont::const_iterator prev_;
typedef typename Icont::iterator iiterator;
typedef typename Icont::const_iterator iconst_iterator;
const iconst_iterator prev_;
iiterator ret_;
public:
insertion_functor(Icont &icont, typename Icont::const_iterator prev)
: icont_(icont), prev_(prev)
: icont_(icont), prev_(prev), ret_(prev.unconst())
{}
void operator()(Node &n)
{ prev_ = this->icont_.insert_after(prev_, n); }
{
ret_ = this->icont_.insert_after(prev_, n);
}
iiterator inserted_first() const
{ return ret_; }
};
template<class FwdIterator>
void priv_create_and_insert_nodes
(const_iterator prev, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
{
//Optimized allocation and construction
this->allocate_many_and_construct
(beg, std::distance(beg, end), insertion_functor(this->icont(), prev.get()));
}
//Default constructed version
void priv_create_and_insert_nodes(const_iterator prev, size_type n)
{
typedef default_construct_iterator<value_type, difference_type> default_iterator;
this->priv_create_and_insert_nodes(prev, default_iterator(n), default_iterator());
}
//Copy constructed version
void priv_create_and_insert_nodes(const_iterator prev, size_type n, const T& x)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
this->priv_create_and_insert_nodes(prev, cvalue_iterator(x, n), cvalue_iterator());
}
//Dispatch to detect iterator range or integer overloads
template <class InputIter>
void priv_insert_dispatch(const_iterator prev,
InputIter first, InputIter last,
container_detail::false_)
{ this->priv_create_and_insert_nodes(prev, first, last); }
template<class Integer>
void priv_insert_dispatch(const_iterator prev, Integer n, Integer x, container_detail::true_)
{ this->priv_create_and_insert_nodes(prev, (size_type)n, x); }
void priv_fill_assign(size_type n, const T& val)
{
iterator end_n(this->end());
iterator prev(this->before_begin());
iterator node(this->begin());
for ( ; node != end_n && n > 0 ; --n){
*node = val;
prev = node;
++node;
}
if (n > 0)
this->priv_create_and_insert_nodes(prev, n, val);
else
this->erase_after(prev, end_n);
}
template <class Int>
void priv_assign_dispatch(Int n, Int val, container_detail::true_)
{ this->priv_fill_assign((size_type) n, (T)val); }
template <class InpIt>
void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
{
iterator end_n(this->end());
iterator prev(this->before_begin());
iterator node(this->begin());
while (node != end_n && first != last){
*node = *first;
prev = node;
++node;
++first;
}
if (first != last)
this->priv_create_and_insert_nodes(prev, first, last);
else
this->erase_after(prev, end_n);
}
template <class Int>
void priv_insert_after_range_dispatch(const_iterator prev_pos, Int n, Int x, container_detail::true_)
{ this->priv_create_and_insert_nodes(prev_pos, (size_type)n, x); }
template <class InIter>
void priv_insert_after_range_dispatch(const_iterator prev_pos, InIter first, InIter last, container_detail::false_)
{ this->priv_create_and_insert_nodes(prev_pos, first, last); }
//Functors for member algorithm defaults
struct value_less
{

View File

@@ -93,7 +93,7 @@ class clear_on_destroy
{
if(do_clear_){
c_.clear();
c_.clear_pool();
c_.priv_clear_pool();
}
}
@@ -172,6 +172,9 @@ class iterator
iterator(const iterator<T, T&, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>& x)
: pn(x.pn)
{}
node_type_ptr_t node() const
{ return pn; }
private:
static node_type_ptr_t node_ptr_cast(const void_ptr &p)
@@ -413,14 +416,14 @@ class stable_vector
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ return node_alloc().allocate(1); }
{ return this->priv_node_alloc().allocate(1); }
template<class AllocatorVersion>
node_type_ptr_t allocate_one(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ return node_alloc().allocate_one(); }
{ return this->priv_node_alloc().allocate_one(); }
void deallocate_one(node_type_ptr_t p)
{ return this->deallocate_one(p, alloc_version()); }
@@ -430,14 +433,14 @@ class stable_vector
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ node_alloc().deallocate(p, 1); }
{ this->priv_node_alloc().deallocate(p, 1); }
template<class AllocatorVersion>
void deallocate_one(node_type_ptr_t p, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{ node_alloc().deallocate_one(p); }
{ this->priv_node_alloc().deallocate_one(p); }
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
///@endcond
@@ -497,7 +500,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Constant.
explicit stable_vector(const allocator_type& al)
: internal_data(al),impl(al)
: internal_data(al), impl(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
}
@@ -510,7 +513,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
explicit stable_vector(size_type n)
: internal_data(),impl()
: internal_data(), impl()
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->resize(n);
@@ -526,10 +529,10 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
: internal_data(al),impl(al)
: internal_data(al), impl(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), n, t);
this->insert(this->cend(), n, t);
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -543,10 +546,10 @@ class stable_vector
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InputIterator>
stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
: internal_data(al),impl(al)
: internal_data(al), impl(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), first, last);
this->insert(this->cend(), first, last);
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -558,12 +561,12 @@ class stable_vector
//! <b>Complexity</b>: Linear to the elements x contains.
stable_vector(const stable_vector& x)
: internal_data(allocator_traits<node_allocator_type>::
select_on_container_copy_construction(x.node_alloc()))
select_on_container_copy_construction(x.priv_node_alloc()))
, impl(allocator_traits<allocator_type>::
select_on_container_copy_construction(x.impl.get_stored_allocator()))
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), x.begin(), x.end());
this->insert(this->cend(), x.begin(), x.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -574,7 +577,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Constant.
stable_vector(BOOST_RV_REF(stable_vector) x)
: internal_data(boost::move(x.node_alloc())), impl(boost::move(x.impl))
: internal_data(boost::move(x.priv_node_alloc())), impl(boost::move(x.impl))
{
this->priv_swap_members(x);
}
@@ -588,7 +591,7 @@ class stable_vector
: internal_data(a), impl(a)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), x.begin(), x.end());
this->insert(this->cend(), x.begin(), x.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -602,12 +605,12 @@ class stable_vector
stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
: internal_data(a), impl(a)
{
if(this->node_alloc() == x.node_alloc()){
if(this->priv_node_alloc() == x.priv_node_alloc()){
this->priv_swap_members(x);
}
else{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cbegin(), x.begin(), x.end());
this->insert(this->cend(), x.begin(), x.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -622,7 +625,7 @@ class stable_vector
~stable_vector()
{
this->clear();
clear_pool();
priv_clear_pool();
}
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -637,15 +640,15 @@ class stable_vector
{
STABLE_VECTOR_CHECK_INVARIANT;
if (&x != this){
node_allocator_type &this_alloc = this->node_alloc();
const node_allocator_type &x_alloc = x.node_alloc();
node_allocator_type &this_alloc = this->priv_node_alloc();
const node_allocator_type &x_alloc = x.priv_node_alloc();
container_detail::bool_<allocator_traits_type::
propagate_on_container_copy_assignment::value> flag;
if(flag && this_alloc != x_alloc){
this->clear();
this->shrink_to_fit();
}
container_detail::assign_alloc(this->node_alloc(), x.node_alloc(), flag);
container_detail::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
container_detail::assign_alloc(this->impl.get_stored_allocator(), x.impl.get_stored_allocator(), flag);
this->assign(x.begin(), x.end());
}
@@ -663,8 +666,8 @@ class stable_vector
stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
{
if (&x != this){
node_allocator_type &this_alloc = this->node_alloc();
node_allocator_type &x_alloc = x.node_alloc();
node_allocator_type &this_alloc = this->priv_node_alloc();
node_allocator_type &x_alloc = x.priv_node_alloc();
//If allocators are equal we can just swap pointers
if(this_alloc == x_alloc){
//Destroy objects but retain memory
@@ -674,7 +677,7 @@ class stable_vector
//Move allocator if needed
container_detail::bool_<allocator_traits_type::
propagate_on_container_move_assignment::value> flag;
container_detail::move_alloc(this->node_alloc(), x.node_alloc(), flag);
container_detail::move_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
}
//If unequal allocators, then do a one by one move
else{
@@ -693,9 +696,25 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
template<typename InputIterator>
void assign(InputIterator first,InputIterator last)
void assign(InputIterator first,InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIterator, size_type>::value
>::type * = 0
#endif
)
{
assign_dispatch(first, last, boost::is_integral<InputIterator>());
STABLE_VECTOR_CHECK_INVARIANT;
iterator first1 = this->begin();
iterator last1 = this->end();
for ( ; first1 != last1 && first != last; ++first1, ++first)
*first1 = *first;
if (first == last){
this->erase(first1, last1);
}
else{
this->insert(last1, first, last);
}
}
@@ -707,7 +726,7 @@ class stable_vector
void assign(size_type n,const T& t)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
this->assign(cvalue_iterator(t, n), cvalue_iterator());
}
//! <b>Effects</b>: Returns a copy of the internal allocator.
@@ -715,7 +734,8 @@ class stable_vector
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
allocator_type get_allocator()const {return this->node_alloc();}
allocator_type get_allocator()const
{ return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -725,7 +745,7 @@ class stable_vector
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return node_alloc(); }
{ return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -735,7 +755,7 @@ class stable_vector
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return node_alloc(); }
{ return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
@@ -928,7 +948,7 @@ class stable_vector
}
//Now fill pool if data is not enough
if((n - size) > this->internal_data.pool_size){
this->add_to_pool((n - size) - this->internal_data.pool_size);
this->priv_add_to_pool((n - size) - this->internal_data.pool_size);
}
}
}
@@ -1066,6 +1086,8 @@ class stable_vector
//!
//! <b>Effects</b>: Insert a copy of x before position.
//!
//! <b>Returns</b>: An iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1086,6 +1108,8 @@ class stable_vector
//!
//! <b>Effects</b>: Insert a new element before position with mx's resources.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1104,33 +1128,70 @@ class stable_vector
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert n copies of x before pos.
//! <b>Effects</b>: Insert n copies of x before position.
//!
//! <b>Returns</b>: an iterator to the first inserted element or position if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
void insert(const_iterator position, size_type n, const T& t)
iterator insert(const_iterator position, size_type n, const T& t)
{
STABLE_VECTOR_CHECK_INVARIANT;
this->insert_not_iter(position, n, t);
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->insert(position, cvalue_iterator(t, n), cvalue_iterator());
}
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InputIterator>
void insert(const_iterator position,InputIterator first, InputIterator last)
iterator insert(const_iterator position,InputIterator first, InputIterator last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIterator, size_type>::value
&& container_detail::is_input_iterator<InputIterator>::value
>::type * = 0
#endif
)
{
STABLE_VECTOR_CHECK_INVARIANT;
this->insert_iter(position,first,last,
boost::mpl::not_<boost::is_integral<InputIterator> >());
const size_type pos_n = position - this->cbegin();
for(; first != last; ++first){
this->emplace(position, *first);
}
return this->begin() + pos_n;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator position, FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
)
{
size_type n = (size_type)std::distance(first,last);
difference_type d = position - this->cbegin();
if(n){
this->insert_iter_prolog(n, d);
const impl_iterator it(impl.begin() + d);
this->priv_insert_iter_fwd(it, first, last, n);
//Fix the pointers for the newly allocated buffer
this->align_nodes(it + n, get_last_align());
}
return this->begin() + d;
}
#endif
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
@@ -1230,7 +1291,18 @@ class stable_vector
//! <b>Complexity</b>: Linear to the distance between first and last
//! plus linear to the elements between pos and the last element.
iterator erase(const_iterator first, const_iterator last)
{ return priv_erase(first, last, alloc_version()); }
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
if(d1 != d2){
impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2);
for(impl_iterator it = it1; it != it2; ++it)
this->delete_node(*it);
impl_iterator e = impl.erase(it1, it2);
this->align_nodes(e, get_last_align());
}
return iterator(this->begin() + d1);
}
//! <b>Effects</b>: Swaps the contents of *this and x.
//!
@@ -1241,7 +1313,7 @@ class stable_vector
{
STABLE_VECTOR_CHECK_INVARIANT;
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
container_detail::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
//vector's allocator is swapped here
this->impl.swap(x.impl);
this->priv_swap_members(x);
@@ -1265,7 +1337,7 @@ class stable_vector
{
if(this->capacity()){
//First empty allocated node pool
this->clear_pool();
this->priv_clear_pool();
//If empty completely destroy the index, let's recover default-constructed state
if(this->empty()){
this->impl.clear();
@@ -1291,14 +1363,14 @@ class stable_vector
iterator priv_insert(const_iterator position, const value_type &t)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
return this->insert_iter(position, cvalue_iterator(t, 1), cvalue_iterator(), std::forward_iterator_tag());
return this->insert(position, cvalue_iterator(t, 1), cvalue_iterator());
}
void priv_push_back(const value_type &t)
{ this->insert(end(), t); }
template<class AllocatorVersion>
void clear_pool(AllocatorVersion,
void priv_clear_pool(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
@@ -1320,7 +1392,7 @@ class stable_vector
}
template<class AllocatorVersion>
void clear_pool(AllocatorVersion,
void priv_clear_pool(AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
@@ -1330,24 +1402,24 @@ class stable_vector
void_ptr &pool_last_ref = impl.back();
multiallocation_chain holder;
holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
node_alloc().deallocate_individual(boost::move(holder));
this->priv_node_alloc().deallocate_individual(boost::move(holder));
pool_first_ref = pool_last_ref = 0;
this->internal_data.pool_size = 0;
}
}
void clear_pool()
void priv_clear_pool()
{
this->clear_pool(alloc_version());
this->priv_clear_pool(alloc_version());
}
void add_to_pool(size_type n)
void priv_add_to_pool(size_type n)
{
this->add_to_pool(n, alloc_version());
this->priv_add_to_pool(n, alloc_version());
}
template<class AllocatorVersion>
void add_to_pool(size_type n, AllocatorVersion,
void priv_add_to_pool(size_type n, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
@@ -1359,7 +1431,7 @@ class stable_vector
}
template<class AllocatorVersion>
void add_to_pool(size_type n, AllocatorVersion,
void priv_add_to_pool(size_type n, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
@@ -1369,7 +1441,7 @@ class stable_vector
multiallocation_chain holder;
holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
//BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<multiallocation_chain>::value == true));
multiallocation_chain m (node_alloc().allocate_individual(n));
multiallocation_chain m (this->priv_node_alloc().allocate_individual(n));
holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
this->internal_data.pool_size += n;
std::pair<void_ptr, void_ptr> data(holder.extract_data());
@@ -1390,7 +1462,7 @@ class stable_vector
pool_last_ref = ret.second;
}
node_type_ptr_t get_from_pool()
node_type_ptr_t priv_get_from_pool()
{
if(!impl.back()){
return node_type_ptr_t(0);
@@ -1429,43 +1501,6 @@ class stable_vector
}
}
template<typename InputIterator>
void assign_dispatch(InputIterator first, InputIterator last, boost::mpl::false_)
{
STABLE_VECTOR_CHECK_INVARIANT;
iterator first1 = this->begin();
iterator last1 = this->end();
for ( ; first1 != last1 && first != last; ++first1, ++first)
*first1 = *first;
if (first == last){
this->erase(first1, last1);
}
else{
this->insert(last1, first, last);
}
}
template<typename Integer>
void assign_dispatch(Integer n, Integer t, boost::mpl::true_)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
this->assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
}
iterator priv_erase(const_iterator first, const_iterator last, allocator_v1)
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
if(d1 != d2){
impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2);
for(impl_iterator it = it1; it != it2; ++it)
this->delete_node(*it);
impl_iterator e = impl.erase(it1, it2);
this->align_nodes(e, get_last_align());
}
return iterator(this->begin() + d1);
}
impl_iterator get_last_align()
{
return impl.end() - (ExtraPointers - 1);
@@ -1476,16 +1511,6 @@ class stable_vector
return impl.cend() - (ExtraPointers - 1);
}
template<class AllocatorVersion>
iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
::value>::type * = 0)
{
STABLE_VECTOR_CHECK_INVARIANT;
return priv_erase(first, last, allocator_v1());
}
static node_type_ptr_t node_ptr_cast(const void_ptr &p)
{
return node_type_ptr_t(static_cast<node_type_t*>(container_detail::to_raw_pointer(p)));
@@ -1535,7 +1560,7 @@ class stable_vector
{
node_type_ptr_t p = this->allocate_one();
try{
boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), it);
boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), it);
//This does not throw
::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
p->set_pointer(up);
@@ -1551,7 +1576,7 @@ class stable_vector
{
node_type_ptr_t n(node_ptr_cast(p));
allocator_traits<node_allocator_type>::
destroy(this->node_alloc(), container_detail::to_raw_pointer(n));
destroy(this->priv_node_alloc(), container_detail::to_raw_pointer(n));
this->put_in_pool(n);
}
@@ -1563,44 +1588,8 @@ class stable_vector
}
}
void insert_not_iter(const_iterator position, size_type n, const T& t)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
this->insert_iter(position, cvalue_iterator(t, n), cvalue_iterator(), std::forward_iterator_tag());
}
template <class InputIterator>
void insert_iter(const_iterator position,InputIterator first,InputIterator last, boost::mpl::true_)
{
typedef typename std::iterator_traits<InputIterator>::iterator_category category;
this->insert_iter(position, first, last, category());
}
template <class InputIterator>
void insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag)
{
for(; first!=last; ++first){
this->insert(position, *first);
}
}
template <class InputIterator>
iterator insert_iter(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
{
size_type n = (size_type)std::distance(first,last);
difference_type d = position-this->cbegin();
if(n){
this->insert_iter_prolog(n, d);
const impl_iterator it(impl.begin() + d);
this->insert_iter_fwd(it, first, last, n);
//Fix the pointers for the newly allocated buffer
this->align_nodes(it + n, get_last_align());
}
return this->begin() + d;
}
template <class FwdIterator>
void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
void priv_insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
{
size_type i=0;
try{
@@ -1618,9 +1607,9 @@ class stable_vector
}
template <class FwdIterator>
void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
void priv_insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
{
multiallocation_chain mem(node_alloc().allocate_individual(n));
multiallocation_chain mem(this->priv_node_alloc().allocate_individual(n));
size_type i = 0;
node_type_ptr_t p = 0;
@@ -1629,7 +1618,7 @@ class stable_vector
p = mem.front();
mem.pop_front();
//This can throw
boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), first);
boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first);
//This does not throw
::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
p->set_pointer(void_ptr_ptr(&it[i]));
@@ -1639,8 +1628,8 @@ class stable_vector
}
}
catch(...){
node_alloc().deallocate_one(p);
node_alloc().deallocate_many(boost::move(mem));
this->priv_node_alloc().deallocate_one(p);
this->priv_node_alloc().deallocate_many(boost::move(mem));
impl_iterator e = impl.erase(it+i, it+n);
this->align_nodes(e, get_last_align());
throw;
@@ -1648,19 +1637,19 @@ class stable_vector
}
template <class FwdIterator>
void insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
void priv_insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
{
size_type i = 0;
node_type_ptr_t p = 0;
try{
while(first != last){
p = this->get_from_pool();
p = this->priv_get_from_pool();
if(!p){
insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
this->priv_insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
break;
}
//This can throw
boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), first);
boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first);
//This does not throw
::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
p->set_pointer(void_ptr_ptr(&it[i]));
@@ -1677,14 +1666,15 @@ class stable_vector
}
}
template <class InputIterator>
void insert_iter(const_iterator position, InputIterator first, InputIterator last, boost::mpl::false_)
void priv_swap_members(stable_vector &x)
{
this->insert_not_iter(position, first, last);
container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
this->readjust_end_node();
x.readjust_end_node();
}
#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
bool invariant()const
bool priv_invariant()const
{
if(impl.empty())
return !capacity() && !size();
@@ -1715,7 +1705,7 @@ class stable_vector
public:
invariant_checker(const stable_vector& v):p(&v){}
~invariant_checker(){BOOST_ASSERT(p->invariant());}
~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
void touch(){}
};
#endif
@@ -1725,14 +1715,8 @@ class stable_vector
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
public:
/*
explicit ebo_holder(BOOST_RV_REF(ebo_holder) x)
: node_allocator_type(boost::move(static_cast<node_allocator_type&>(x)))
, pool_size(0)
, end_node()
{}
*/
template<class AllocatorRLValue>
explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
: node_allocator_type(boost::forward<AllocatorRLValue>(a))
@@ -1759,15 +1743,8 @@ class stable_vector
node_type_base_t end_node;
} internal_data;
void priv_swap_members(stable_vector &x)
{
container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
this->readjust_end_node();
x.readjust_end_node();
}
node_allocator_type &node_alloc() { return internal_data; }
const node_allocator_type &node_alloc() const { return internal_data; }
node_allocator_type &priv_node_alloc() { return internal_data; }
const node_allocator_type &priv_node_alloc() const { return internal_data; }
impl_type impl;
/// @endcond

View File

@@ -68,13 +68,8 @@
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/aligned_storage.hpp>
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
#else
namespace boost {
namespace container {
#endif
/// @cond
namespace container_detail {
@@ -624,7 +619,10 @@ class basic_string
//! <b>Throws</b>: If allocator_type's default constructor throws.
basic_string(const basic_string& s)
: base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
{ this->priv_range_initialize(s.begin(), s.end()); }
{
this->priv_terminate_string();
this->assign(s.begin(), s.end());
}
//! <b>Effects</b>: Move constructor. Moves s's resources to *this.
//!
@@ -642,7 +640,10 @@ class basic_string
//! <b>Throws</b>: If allocation throws.
basic_string(const basic_string& s, const allocator_type &a)
: base_t(a)
{ this->priv_range_initialize(s.begin(), s.end()); }
{
this->priv_terminate_string();
this->assign(s.begin(), s.end());
}
//! <b>Effects</b>: Move constructor using the specified allocator.
//! Moves s's resources to *this.
@@ -653,11 +654,12 @@ class basic_string
basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
: base_t(a)
{
this->priv_terminate_string();
if(a == this->alloc()){
this->swap_data(s);
}
else{
this->priv_range_initialize(s.begin(), s.end());
this->assign(s.begin(), s.end());
}
}
@@ -667,10 +669,11 @@ class basic_string
const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_terminate_string();
if (pos > s.size())
this->throw_out_of_range();
else
this->priv_range_initialize
this->assign
(s.begin() + pos, s.begin() + pos + container_detail::min_value(n, s.size() - pos));
}
@@ -679,23 +682,29 @@ class basic_string
basic_string(const CharT* s, size_type n,
const allocator_type& a = allocator_type())
: base_t(a)
{ this->priv_range_initialize(s, s + n); }
{
this->priv_terminate_string();
this->assign(s, s + n);
}
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by the null-terminated s c-string.
basic_string(const CharT* s,
const allocator_type& a = allocator_type())
: base_t(a)
{ this->priv_range_initialize(s, s + Traits::length(s)); }
{
this->priv_terminate_string();
this->assign(s, s + Traits::length(s));
}
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
//! and is initialized by n copies of c.
basic_string(size_type n, CharT c,
const allocator_type& a = allocator_type())
: base_t(a)
{
this->priv_range_initialize(cvalue_iterator(c, n),
cvalue_iterator());
{
this->priv_terminate_string();
this->assign(n, c);
}
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
@@ -705,10 +714,8 @@ class basic_string
const allocator_type& a = allocator_type())
: base_t(a)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InputIterator, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_initialize_dispatch(f, l, Result());
this->priv_terminate_string();
this->assign(f, l);
}
//! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
@@ -1213,8 +1220,8 @@ class basic_string
//! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
//!
//! <b>Returns</b>: *this
basic_string& assign(const basic_string& s,
size_type pos, size_type n) {
basic_string& assign(const basic_string& s, size_type pos, size_type n)
{
if (pos > s.size())
this->throw_out_of_range();
return this->assign(s.begin() + pos,
@@ -1250,12 +1257,28 @@ class basic_string
//!
//! <b>Returns</b>: *this
template <class InputIter>
basic_string& assign(InputIter first, InputIter last)
basic_string& assign(InputIter first, InputIter last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIter, size_type>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
return this->priv_assign_dispatch(first, last, Result());
size_type cur = 0;
CharT *ptr = container_detail::to_raw_pointer(this->priv_addr());
const size_type old_size = this->priv_size();
while (first != last && cur != old_size) {
Traits::assign(*ptr, *first);
++first;
++cur;
++ptr;
}
if (first == last)
this->erase(this->priv_addr() + cur, this->priv_addr() + old_size);
else
this->append(first, last);
return *this;
}
//! <b>Requires</b>: pos <= size().
@@ -1283,8 +1306,7 @@ class basic_string
//! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
//!
//! <b>Returns</b>: *this
basic_string& insert(size_type pos1, const basic_string& s,
size_type pos2, size_type n)
basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n)
{
if (pos1 > this->size() || pos2 > s.size())
this->throw_out_of_range();
@@ -1369,23 +1391,144 @@ class basic_string
//! <b>Requires</b>: p is a valid iterator on *this.
//!
//! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
void insert(const_iterator p, size_type n, CharT c)
{
this->insert(p, cvalue_iterator(c, n), cvalue_iterator());
}
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
iterator insert(const_iterator p, size_type n, CharT c)
{ return this->insert(p, cvalue_iterator(c, n), cvalue_iterator()); }
//! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
//!
//! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
template <class InputIter>
void insert(const_iterator p, InputIter first, InputIter last)
iterator insert(const_iterator p, InputIter first, InputIter last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIter, size_type>::value
&& container_detail::is_input_iterator<InputIter>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_dispatch(p, first, last, Result());
const size_type n_pos = p - this->cbegin();
for ( ; first != last; ++first, ++p) {
p = this->insert(p, *first);
}
return this->begin() + n_pos;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class ForwardIter>
iterator insert(const_iterator p, ForwardIter first, ForwardIter last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<ForwardIter, size_type>::value
&& !container_detail::is_input_iterator<ForwardIter>::value
>::type * = 0
)
{
const size_type n_pos = p - this->cbegin();
if (first != last) {
const size_type n = std::distance(first, last);
const size_type old_size = this->priv_size();
const size_type remaining = this->capacity() - old_size;
const pointer old_start = this->priv_addr();
bool enough_capacity = false;
std::pair<pointer, bool> allocation_ret;
size_type new_cap = 0;
//Check if we have enough capacity
if (remaining >= n){
enough_capacity = true;
}
else {
//Otherwise expand current buffer or allocate new storage
new_cap = this->next_capacity(n);
allocation_ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd, old_size + n + 1,
new_cap, new_cap, old_start);
//Check forward expansion
if(old_start == allocation_ret.first){
enough_capacity = true;
this->priv_storage(new_cap);
}
}
//Reuse same buffer
if(enough_capacity){
const size_type elems_after = old_size - (p - this->priv_addr());
const size_type old_length = old_size;
if (elems_after >= n) {
const pointer pointer_past_last = this->priv_addr() + old_size + 1;
priv_uninitialized_copy(this->priv_addr() + (old_size - n + 1),
pointer_past_last, pointer_past_last);
this->priv_size(old_size+n);
Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(p + n)),
container_detail::to_raw_pointer(p),
(elems_after - n) + 1);
this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
}
else {
ForwardIter mid = first;
std::advance(mid, elems_after + 1);
priv_uninitialized_copy(mid, last, this->priv_addr() + old_size + 1);
this->priv_size(old_size + (n - elems_after));
priv_uninitialized_copy
(p, const_iterator(this->priv_addr() + old_length + 1),
this->priv_addr() + this->priv_size());
this->priv_size(this->priv_size() + elems_after);
this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
}
}
else{
pointer new_start = allocation_ret.first;
if(!allocation_ret.second){
//Copy data to new buffer
size_type new_length = 0;
//This can't throw, since characters are POD
new_length += priv_uninitialized_copy
(const_iterator(this->priv_addr()), p, new_start);
new_length += priv_uninitialized_copy
(first, last, new_start + new_length);
new_length += priv_uninitialized_copy
(p, const_iterator(this->priv_addr() + old_size),
new_start + new_length);
this->priv_construct_null(new_start + new_length);
this->deallocate_block();
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(new_length);
this->priv_long_storage(new_cap);
}
else{
//value_type is POD, so backwards expansion is much easier
//than with vector<T>
value_type * const oldbuf = container_detail::to_raw_pointer(old_start);
value_type * const newbuf = container_detail::to_raw_pointer(new_start);
const value_type *const pos = container_detail::to_raw_pointer(p);
const size_type before = pos - oldbuf;
//First move old data
Traits::move(newbuf, oldbuf, before);
Traits::move(newbuf + before + n, pos, old_size - before);
//Now initialize the new data
priv_uninitialized_copy(first, last, new_start + before);
this->priv_construct_null(new_start + (old_size + n));
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(old_size + n);
this->priv_long_storage(new_cap);
}
}
}
return this->begin() + n_pos;
}
#endif
//! <b>Requires</b>: pos <= size()
//!
//! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
@@ -1472,8 +1615,9 @@ class basic_string
const size_type len = container_detail::min_value(n1, size() - pos1);
if (this->size() - len >= this->max_size() - str.size())
this->throw_length_error();
return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len,
str.begin(), str.end());
return this->replace( const_iterator(this->priv_addr() + pos1)
, const_iterator(this->priv_addr() + pos1 + len)
, str.begin(), str.end());
}
//! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
@@ -1512,16 +1656,14 @@ class basic_string
//! if the length of the resulting string would exceed max_size()
//!
//! <b>Returns</b>: *this
basic_string& replace(size_type pos1, size_type n1,
const CharT* s, size_type n2)
basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
{
if (pos1 > size())
this->throw_out_of_range();
const size_type len = container_detail::min_value(n1, size() - pos1);
if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
this->throw_length_error();
return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len,
s, s + n2);
return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, s, s + n2);
}
//! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
@@ -1629,14 +1771,51 @@ class basic_string
//!
//! <b>Returns</b>: *this
template <class InputIter>
basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2)
basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InputIter, size_type>::value
&& container_detail::is_input_iterator<InputIter>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
return this->priv_replace_dispatch(i1, i2, j1, j2, Result());
for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
Traits::assign(*const_cast<CharT*>(container_detail::to_raw_pointer(i1)), *j1);
}
if (j1 == j2)
this->erase(i1, i2);
else
this->insert(i2, j1, j2);
return *this;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class ForwardIter>
basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
, typename container_detail::enable_if_c
< !container_detail::is_convertible<ForwardIter, size_type>::value
&& !container_detail::is_input_iterator<ForwardIter>::value
>::type * = 0
)
{
difference_type n = std::distance(j1, j2);
const difference_type len = i2 - i1;
if (len >= n) {
this->priv_copy(j1, j2, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
this->erase(i1 + n, i2);
}
else {
ForwardIter m = j1;
std::advance(m, len);
this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
this->insert(i2, m, j2);
}
return *this;
}
#endif
//! <b>Requires</b>: pos <= size()
//!
//! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
@@ -2153,46 +2332,6 @@ class basic_string
void priv_terminate_string()
{ this->priv_construct_null(this->priv_addr() + this->priv_size()); }
template <class InputIter>
void priv_range_initialize(InputIter f, InputIter l,
std::input_iterator_tag)
{
this->allocate_initial_block(InternalBufferChars);
this->priv_construct_null(this->priv_addr() + this->priv_size());
this->append(f, l);
}
template <class ForwardIter>
void priv_range_initialize(ForwardIter f, ForwardIter l,
std::forward_iterator_tag)
{
difference_type n = std::distance(f, l);
this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
priv_uninitialized_copy(f, l, this->priv_addr());
this->priv_size(n);
this->priv_terminate_string();
}
template <class InputIter>
void priv_range_initialize(InputIter f, InputIter l)
{
typedef typename std::iterator_traits<InputIter>::iterator_category Category;
this->priv_range_initialize(f, l, Category());
}
template <class Integer>
void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
{
this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
priv_uninitialized_fill_n(this->priv_addr(), n, x);
this->priv_size(n);
this->priv_terminate_string();
}
template <class InputIter>
void priv_initialize_dispatch(InputIter f, InputIter l, container_detail::false_)
{ this->priv_range_initialize(f, l); }
template<class FwdIt, class Count> inline
void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
{
@@ -2238,14 +2377,9 @@ class basic_string
BOOST_CATCH_END
return (constructed);
}
template <class Integer>
basic_string& priv_assign_dispatch(Integer n, Integer x, container_detail::true_)
{ return this->assign((size_type) n, (CharT) x); }
/*
template <class InputIter>
basic_string& priv_assign_dispatch(InputIter f, InputIter l,
container_detail::false_)
basic_string& priv_assign_dispatch(InputIter f, InputIter l, container_detail::false_)
{
size_type cur = 0;
CharT *ptr = container_detail::to_raw_pointer(this->priv_addr());
@@ -2262,131 +2396,7 @@ class basic_string
this->append(f, l);
return *this;
}
template <class InputIter>
void priv_insert(const_iterator p, InputIter first, InputIter last, std::input_iterator_tag)
{
for ( ; first != last; ++first, ++p) {
p = this->insert(p, *first);
}
}
template <class ForwardIter>
void priv_insert(const_iterator position, ForwardIter first,
ForwardIter last, std::forward_iterator_tag)
{
if (first != last) {
const size_type n = std::distance(first, last);
const size_type old_size = this->priv_size();
const size_type remaining = this->capacity() - old_size;
const pointer old_start = this->priv_addr();
bool enough_capacity = false;
std::pair<pointer, bool> allocation_ret;
size_type new_cap = 0;
//Check if we have enough capacity
if (remaining >= n){
enough_capacity = true;
}
else {
//Otherwise expand current buffer or allocate new storage
new_cap = this->next_capacity(n);
allocation_ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd, old_size + n + 1,
new_cap, new_cap, old_start);
//Check forward expansion
if(old_start == allocation_ret.first){
enough_capacity = true;
this->priv_storage(new_cap);
}
}
//Reuse same buffer
if(enough_capacity){
const size_type elems_after = old_size - (position - this->priv_addr());
const size_type old_length = old_size;
if (elems_after >= n) {
const pointer pointer_past_last = this->priv_addr() + old_size + 1;
priv_uninitialized_copy(this->priv_addr() + (old_size - n + 1),
pointer_past_last, pointer_past_last);
this->priv_size(old_size+n);
Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(position + n)),
container_detail::to_raw_pointer(position),
(elems_after - n) + 1);
this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
}
else {
ForwardIter mid = first;
std::advance(mid, elems_after + 1);
priv_uninitialized_copy(mid, last, this->priv_addr() + old_size + 1);
this->priv_size(old_size + (n - elems_after));
priv_uninitialized_copy
(position, const_iterator(this->priv_addr() + old_length + 1),
this->priv_addr() + this->priv_size());
this->priv_size(this->priv_size() + elems_after);
this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
}
}
else{
pointer new_start = allocation_ret.first;
if(!allocation_ret.second){
//Copy data to new buffer
size_type new_length = 0;
//This can't throw, since characters are POD
new_length += priv_uninitialized_copy
(const_iterator(this->priv_addr()), position, new_start);
new_length += priv_uninitialized_copy
(first, last, new_start + new_length);
new_length += priv_uninitialized_copy
(position, const_iterator(this->priv_addr() + old_size),
new_start + new_length);
this->priv_construct_null(new_start + new_length);
this->deallocate_block();
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(new_length);
this->priv_long_storage(new_cap);
}
else{
//value_type is POD, so backwards expansion is much easier
//than with vector<T>
value_type * const oldbuf = container_detail::to_raw_pointer(old_start);
value_type * const newbuf = container_detail::to_raw_pointer(new_start);
const value_type *const pos = container_detail::to_raw_pointer(position);
const size_type before = pos - oldbuf;
//First move old data
Traits::move(newbuf, oldbuf, before);
Traits::move(newbuf + before + n, pos, old_size - before);
//Now initialize the new data
priv_uninitialized_copy(first, last, new_start + before);
this->priv_construct_null(new_start + (old_size + n));
this->is_short(false);
this->priv_long_addr(new_start);
this->priv_long_size(old_size + n);
this->priv_long_storage(new_cap);
}
}
}
}
template <class Integer>
void priv_insert_dispatch(const_iterator p, Integer n, Integer x,
container_detail::true_)
{ insert(p, (size_type) n, (CharT) x); }
template <class InputIter>
void priv_insert_dispatch(const_iterator p, InputIter first, InputIter last,
container_detail::false_)
{
typedef typename std::iterator_traits<InputIter>::iterator_category Category;
priv_insert(p, first, last, Category());
}
*/
template <class InputIterator, class OutIterator>
void priv_copy(InputIterator first, InputIterator last, OutIterator result)
{
@@ -2412,40 +2422,6 @@ class basic_string
return this->priv_replace(first, last, f, l, Category());
}
template <class InputIter>
basic_string& priv_replace(const_iterator first, const_iterator last,
InputIter f, InputIter l, std::input_iterator_tag)
{
for ( ; first != last && f != l; ++first, ++f)
Traits::assign(*first, *f);
if (f == l)
this->erase(first, last);
else
this->insert(last, f, l);
return *this;
}
template <class ForwardIter>
basic_string& priv_replace(const_iterator first, const_iterator last,
ForwardIter f, ForwardIter l,
std::forward_iterator_tag)
{
difference_type n = std::distance(f, l);
const difference_type len = last - first;
if (len >= n) {
this->priv_copy(f, l, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
this->erase(first + n, last);
}
else {
ForwardIter m = f;
std::advance(m, len);
this->priv_copy(f, m, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
this->insert(last, m, l);
}
return *this;
}
/// @endcond
};

View File

@@ -489,8 +489,10 @@ class vector : private container_detail::vector_alloc_holder<A>
explicit vector(size_type n)
: base_t()
{
this->resize(n);
/*
//Allocate
size_type real_cap;
size_type real_cap = 0;
std::pair<pointer, bool> ret =
this->allocation_command(allocate_new, n, n, real_cap, this->members_.m_start);
T *new_mem = container_detail::to_raw_pointer(ret.first);
@@ -503,7 +505,7 @@ class vector : private container_detail::vector_alloc_holder<A>
this->members_.m_start = ret.first;
this->members_.m_size = n;
this->members_.m_capacity = real_cap;
scoped_alloc.release();
scoped_alloc.release();*/
}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -515,7 +517,10 @@ class vector : private container_detail::vector_alloc_holder<A>
//! <b>Complexity</b>: Linear to n.
vector(size_type n, const T& value, const allocator_type& a = allocator_type())
: base_t(a)
{ this->insert(this->cend(), n, value); }
{
this->resize(n, value);
// this->insert(this->cend(), n, value);
}
//! <b>Effects</b>: Copy constructs a vector.
//!
@@ -571,7 +576,7 @@ class vector : private container_detail::vector_alloc_holder<A>
}
else{
this->assign( container_detail::to_raw_pointer(mx.members_.m_start)
, container_detail::to_raw_pointer(mx.members_.m_start + mx.members_.m_size));
, container_detail::to_raw_pointer(mx.members_.m_start) + mx.members_.m_size);
}
}
@@ -1002,14 +1007,155 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Linear to n.
template <class InIt>
void assign(InIt first, InIt last)
void assign(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
//Overwrite all elements we can from [first, last)
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first){
*cur = *first;
}
if (first == last){
//There are no more elements in the sequence, erase remaining
this->erase(cur, cend());
}
else{
//There are more elements in the range, insert the remaining ones
this->insert(this->cend(), first, last);
}
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
void assign(FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
)
{
const size_type n = std::distance(first, last);
if(!n){
this->prot_destroy_all();
return;
}
//Check if we have enough memory or try to expand current memory
size_type remaining = this->members_.m_capacity - this->members_.m_size;
bool same_buffer_start;
std::pair<pointer, bool> ret;
size_type real_cap = this->members_.m_capacity;
if (n <= remaining){
same_buffer_start = true;
}
else{
//There is not enough memory, allocate a new buffer
size_type new_cap = this->next_capacity(n);
ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->size() + n, new_cap, real_cap, this->members_.m_start);
same_buffer_start = ret.second && this->members_.m_start == ret.first;
if(same_buffer_start){
this->members_.m_capacity = real_cap;
}
}
if(same_buffer_start){
T *start = container_detail::to_raw_pointer(this->members_.m_start);
if (this->size() >= n){
//There is memory, but there are more old elements than new ones
//Overwrite old elements with new ones
std::copy(first, last, start);
//Destroy remaining old elements
this->destroy_n(start + n, this->members_.m_size - n);
this->members_.m_size = n;
}
else{
//There is memory, but there are less old elements than new ones
//First overwrite some old elements with new ones
FwdIt mid = first;
std::advance(mid, this->size());
T *end = std::copy(first, mid, start);
//Initialize the remaining new elements in the uninitialized memory
::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), mid, last, end);
this->members_.m_size = n;
}
}
else if(!ret.second){
typename value_traits::ArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), first, last, container_detail::to_raw_pointer(ret.first));
scoped_alloc.release();
//Destroy and deallocate old buffer
if(this->members_.m_start != 0){
this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
}
this->members_.m_start = ret.first;
this->members_.m_size = n;
this->members_.m_capacity = real_cap;
}
else{
//Backwards expansion
//If anything goes wrong, this object will destroy old objects
T *old_start = container_detail::to_raw_pointer(this->members_.m_start);
size_type old_size = this->members_.m_size;
typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
//If something goes wrong size will be 0
//but holding the whole buffer
this->members_.m_size = 0;
this->members_.m_start = ret.first;
this->members_.m_capacity = real_cap;
//Backup old buffer data
size_type old_offset = old_start - container_detail::to_raw_pointer(ret.first);
size_type first_count = container_detail::min_value(n, old_offset);
FwdIt mid = first;
std::advance(mid, first_count);
::boost::container::uninitialized_copy_or_move_alloc
(this->alloc(), first, mid, container_detail::to_raw_pointer(ret.first));
if(old_offset > n){
//All old elements will be destroyed by "old_values_destroyer"
this->members_.m_size = n;
}
else{
//We have constructed objects from the new begin until
//the old end so release the rollback destruction
old_values_destroyer.release();
this->members_.m_start = ret.first;
this->members_.m_size = first_count + old_size;
//Now overwrite the old values
size_type second_count = container_detail::min_value(old_size, n - first_count);
FwdIt mid2 = mid;
std::advance(mid2, second_count);
std::copy(mid, mid2, old_start);
//Check if we still have to append elements in the
//uninitialized end
if(second_count == old_size){
std::copy(mid2, last, old_start + old_size);
}
else{
//We have to destroy some old values
this->destroy_n
(old_start + second_count, old_size - second_count);
this->members_.m_size = n;
}
this->members_.m_size = n;
}
}
}
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts a copy of x at the end of the vector.
//!
@@ -1051,7 +1197,7 @@ class vector : private container_detail::vector_alloc_holder<A>
else{
typedef container_detail::advanced_insert_aux_emplace<A, T*, Args...> type;
type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
priv_range_insert(back_pos, 1, proxy);
this->priv_forward_range_insert(back_pos, 1, proxy);
}
}
@@ -1072,7 +1218,7 @@ class vector : private container_detail::vector_alloc_holder<A>
size_type pos_n = position - cbegin();
typedef container_detail::advanced_insert_aux_emplace<A, T*, Args...> type;
type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
priv_range_insert(position.get_ptr(), 1, proxy);
this->priv_forward_range_insert(position.get_ptr(), 1, proxy);
return iterator(this->members_.m_start + pos_n);
}
@@ -1093,7 +1239,7 @@ class vector : private container_detail::vector_alloc_holder<A>
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<A, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_range_insert(back_pos, 1, proxy); \
this->priv_forward_range_insert(back_pos, 1, proxy); \
} \
} \
\
@@ -1105,7 +1251,7 @@ class vector : private container_detail::vector_alloc_holder<A>
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<A, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
priv_range_insert(container_detail::to_raw_pointer(pos.get_ptr()), 1, proxy); \
this->priv_forward_range_insert(container_detail::to_raw_pointer(pos.get_ptr()), 1,proxy);\
return iterator(this->members_.m_start + pos_n); \
} \
//!
@@ -1152,32 +1298,63 @@ class vector : private container_detail::vector_alloc_holder<A>
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
#endif
//! <b>Requires</b>: pos must be a valid iterator of *this.
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InIt>
void insert(const_iterator pos, InIt first, InIt last)
iterator insert(const_iterator pos, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_dispatch(pos, first, last, Result());
const size_type n_pos = pos - this->cbegin();
iterator it(pos.get_ptr());
for(;first != last; ++first){
it = this->emplace(it, *first);
++it;
}
return this->begin() + n_pos;
}
//! <b>Requires</b>: pos must be a valid iterator of *this.
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator pos, FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
)
{
const size_type n_pos = pos - this->cbegin();
const size_type n = std::distance(first, last);
container_detail::advanced_insert_aux_proxy<A, FwdIt, T*> proxy(this->alloc(), first, last);
this->priv_forward_range_insert(pos.get_ptr(), n, proxy);
return this->begin() + n_pos;
}
#endif
//! <b>Requires</b>: p must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert n copies of x before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
void insert(const_iterator p, size_type n, const T& x)
{ this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); }
iterator insert(const_iterator p, size_type n, const T& x)
{ return this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); }
//! <b>Effects</b>: Removes the last element from the vector.
//!
@@ -1262,10 +1439,10 @@ class vector : private container_detail::vector_alloc_holder<A>
this->erase(const_iterator(this->members_.m_start + new_size), this->end());
}
else{
size_type n = new_size - this->size();
const size_type n = new_size - this->size();
this->reserve(new_size);
container_detail::default_construct_aux_proxy<A, T*> proxy(this->alloc(), n);
priv_range_insert(this->cend().get_ptr(), n, proxy);
this->priv_forward_range_insert(this->cend().get_ptr(), n, proxy);
}
}
@@ -1399,27 +1576,7 @@ class vector : private container_detail::vector_alloc_holder<A>
}
}
template <class FwdIt>
void priv_range_insert(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
{
if(first != last){
const size_type n = std::distance(first, last);
container_detail::advanced_insert_aux_proxy<A, FwdIt, T*> proxy(this->alloc(), first, last);
priv_range_insert(pos.get_ptr(), n, proxy);
}
}
template <class InIt>
void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag)
{
iterator it(pos.get_ptr());
for(;first != last; ++first){
it = this->emplace(it, *first);
++it;
}
}
void priv_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf)
void priv_forward_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf)
{
//Check if we have enough memory or try to expand current memory
size_type remaining = this->members_.m_capacity - this->members_.m_size;
@@ -1575,7 +1732,7 @@ class vector : private container_detail::vector_alloc_holder<A>
// |_>_>_>_>_>^
//
//
//New situation in Case B (hole_size >= 0):
//New situation in Case B (hole_size > 0):
// range is moved through uninitialized moves
//
// first_pos last_pos old_limit
@@ -2001,173 +2158,10 @@ class vector : private container_detail::vector_alloc_holder<A>
}
}
template <class InIt>
void priv_assign_aux(InIt first, InIt last, std::input_iterator_tag)
{
//Overwrite all elements we can from [first, last)
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first){
*cur = *first;
}
if (first == last){
//There are no more elements in the sequence, erase remaining
this->erase(cur, cend());
}
else{
//There are more elements in the range, insert the remaining ones
this->insert(this->cend(), first, last);
}
}
template <class FwdIt>
void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
{
size_type n = std::distance(first, last);
if(!n){
this->prot_destroy_all();
return;
}
//Check if we have enough memory or try to expand current memory
size_type remaining = this->members_.m_capacity - this->members_.m_size;
bool same_buffer_start;
std::pair<pointer, bool> ret;
size_type real_cap = this->members_.m_capacity;
if (n <= remaining){
same_buffer_start = true;
}
else{
//There is not enough memory, allocate a new buffer
size_type new_cap = this->next_capacity(n);
ret = this->allocation_command
(allocate_new | expand_fwd | expand_bwd,
this->size() + n, new_cap, real_cap, this->members_.m_start);
same_buffer_start = ret.second && this->members_.m_start == ret.first;
if(same_buffer_start){
this->members_.m_capacity = real_cap;
}
}
if(same_buffer_start){
T *start = container_detail::to_raw_pointer(this->members_.m_start);
if (this->size() >= n){
//There is memory, but there are more old elements than new ones
//Overwrite old elements with new ones
std::copy(first, last, start);
//Destroy remaining old elements
this->destroy_n(start + n, this->members_.m_size - n);
this->members_.m_size = n;
}
else{
//There is memory, but there are less old elements than new ones
//First overwrite some old elements with new ones
FwdIt mid = first;
std::advance(mid, this->size());
// iG T *end = std::copy(first, mid, start);
T *end = std::copy(first, mid, start);
//Initialize the remaining new elements in the uninitialized memory
::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), mid, last, end);
this->members_.m_size = n;
}
}
else if(!ret.second){
typename value_traits::ArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), first, last, container_detail::to_raw_pointer(ret.first));
scoped_alloc.release();
//Destroy and deallocate old buffer
if(this->members_.m_start != 0){
this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
}
this->members_.m_start = ret.first;
this->members_.m_size = n;
this->members_.m_capacity = real_cap;
}
else{
//Backwards expansion
//If anything goes wrong, this object will destroy old objects
T *old_start = container_detail::to_raw_pointer(this->members_.m_start);
size_type old_size = this->members_.m_size;
typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
//If something goes wrong size will be 0
//but holding the whole buffer
this->members_.m_size = 0;
this->members_.m_start = ret.first;
this->members_.m_capacity = real_cap;
//Backup old buffer data
size_type old_offset = old_start - container_detail::to_raw_pointer(ret.first);
size_type first_count = container_detail::min_value(n, old_offset);
FwdIt mid = first;
std::advance(mid, first_count);
::boost::container::uninitialized_copy_or_move_alloc
(this->alloc(), first, mid, container_detail::to_raw_pointer(ret.first));
if(old_offset > n){
//All old elements will be destroyed by "old_values_destroyer"
this->members_.m_size = n;
}
else{
//We have constructed objects from the new begin until
//the old end so release the rollback destruction
old_values_destroyer.release();
this->members_.m_start = ret.first;
this->members_.m_size = first_count + old_size;
//Now overwrite the old values
size_type second_count = container_detail::min_value(old_size, n - first_count);
FwdIt mid2 = mid;
std::advance(mid2, second_count);
// iG std::copy(mid, mid2, old_start);
std::copy(mid, mid2, old_start);
//Check if we still have to append elements in the
//uninitialized end
if(second_count == old_size){
// iG std::copy(mid2, last, old_start + old_size);
std::copy(mid2, last, old_start + old_size);
}
else{
//We have to destroy some old values
this->destroy_n
(old_start + second_count, old_size - second_count);
this->members_.m_size = n;
}
this->members_.m_size = n;
}
}
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
{ this->assign((size_type) n, (value_type)val); }
template <class InIt>
void priv_assign_dispatch(InIt first, InIt last, container_detail::false_)
{
//Dispatch depending on integer/iterator
typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_assign_aux(first, last, ItCat());
}
template <class Integer>
void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, container_detail::true_)
{ this->insert(pos, (size_type)n, (T)val); }
template <class InIt>
void priv_insert_dispatch(const_iterator pos, InIt first,
InIt last, container_detail::false_)
{
//Dispatch depending on integer/iterator
typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_range_insert(pos, first, last, ItCat());
}
void priv_check_range(size_type n) const
{
//If n is out of range, throw an out_of_range exception
if (n >= size())
if (n >= this->size())
throw std::out_of_range("vector::at");
}

View File

@@ -34,6 +34,17 @@ Write forward_list
check move if noexcept conditions in vector, deque and stable_vector
Add noexcept testing using static_assert (Howard Hinnants's suggestion):
#include <type_traits>
struct A
{
void foo() noexcept;
};
static_assert(noexcept(std::declval<A&>().foo()), "A::foo() should be noexcept");
Detect always equal or unequal allocators at compiler time. operator== returns true_type or false_type
change virtual functions with pointers to avoid template instantiation for every type

View File

@@ -132,6 +132,9 @@
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93815995-89BD-b043-5E8B-65FBE52E2AFB}">
<File
RelativePath="..\..\..\..\boost\container\detail\node_alloc_holder.hpp">
</File>
</Filter>
</Files>
<Globals>

View File

@@ -51,6 +51,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scoped_allocator_usage_test
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hash_table_test", "hash_table_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792606}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
@@ -111,6 +115,10 @@ Global
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Debug.Build.0 = Debug|Win32
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.ActiveCfg = Release|Win32
{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.Build.0 = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.ActiveCfg = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Debug.Build.0 = Debug|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.ActiveCfg = Release|Win32
{58CCE183-6092-48FE-A4F7-BA0D3A792606}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View File

@@ -145,6 +145,9 @@
<File
RelativePath="..\..\test\expand_bwd_test_template.hpp">
</File>
<File
RelativePath="..\..\test\forward_to_input_iterator.hpp">
</File>
<File
RelativePath="..\..\test\heap_allocator_v1.hpp">
</File>
@@ -261,7 +264,7 @@
RelativePath="..\..\..\..\boost\container\detail\math_functions.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\allocator\memory_util.hpp">
RelativePath="..\..\..\..\boost\container\detail\memory_util.hpp">
</File>
<File
RelativePath="..\..\..\..\boost\container\detail\mpl.hpp">

View File

@@ -12,6 +12,8 @@
#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/mpl.hpp>
#include <functional>
#include <iostream>
#include <algorithm>
@@ -20,6 +22,24 @@ namespace boost{
namespace container {
namespace test{
template< class T1, class T2>
bool CheckEqual( const T1 &t1, const T2 &t2
, typename boost::container::container_detail::enable_if_c
<!boost::container::container_detail::is_pair<T1>::value &&
!boost::container::container_detail::is_pair<T2>::value
>::type* = 0)
{ return t1 == t2; }
template< class Pair1, class Pair2>
bool CheckEqual( const Pair1 &pair1, const Pair2 &pair2
, typename boost::container::container_detail::enable_if_c
<boost::container::container_detail::is_pair<Pair1>::value &&
boost::container::container_detail::is_pair<Pair2>::value
>::type* = 0)
{
return CheckEqual(pair1.first, pair2.first) && CheckEqual(pair1.second, pair2.second);
}
//Function to check if both containers are equal
template<class MyBoostCont
,class MyStdCont>
@@ -38,10 +58,13 @@ bool CheckEqualContainers(const MyBoostCont *boostcont, const MyStdCont *stdcont
}
std::size_t i = 0;
for(; itboost != itboostend; ++itboost, ++itstd, ++i){
value_type val(*itstd);
if(!CheckEqual(*itstd, *itboost))
return false;
/* value_type val(*itstd);
const value_type &v = *itboost;
if(v != val)
return false;
return false;*/
}
return true;
}

View File

@@ -63,7 +63,7 @@ bool deque_copyable_only(V1 *cntdeque, V2 *stddeque, container_detail::true_type
typedef typename V1::value_type IntType;
std::size_t size = cntdeque->size();
stddeque->insert(stddeque->end(), 50, 1);
cntdeque->insert(cntdeque->end(), 50, 1);
cntdeque->insert(cntdeque->end(), 50, IntType(1));
if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
{
IntType move_me(1);

View File

@@ -0,0 +1,80 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2012-2012. 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_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
#define BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
#include <iterator>
namespace boost{
namespace container {
namespace test{
template<class FwdIterator>
class input_iterator_wrapper
: public std::iterator< std::input_iterator_tag
, typename std::iterator_traits<FwdIterator>::value_type
, typename std::iterator_traits<FwdIterator>::difference_type
, typename std::iterator_traits<FwdIterator>::pointer
, typename std::iterator_traits<FwdIterator>::reference
>
{
FwdIterator m_it;
public:
input_iterator_wrapper()
: m_it(0)
{}
explicit input_iterator_wrapper(FwdIterator it)
: m_it(it)
{}
//Default copy constructor...
//input_iterator_wrapper(const input_iterator_wrapper&);
//Default assignment...
//input_iterator_wrapper &operator=(const input_iterator_wrapper&);
//Default destructor...
//~input_iterator_wrapper();
typename std::iterator_traits<FwdIterator>::reference operator*() const
{ return *m_it; }
typename std::iterator_traits<FwdIterator>::pointer operator->() const
{ return m_it.operator->(); }
input_iterator_wrapper& operator++()
{ ++m_it; return *this; }
input_iterator_wrapper operator++(int )
{
input_iterator_wrapper tmp(m_it);
++m_it;
return tmp;
}
friend bool operator==(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
{ return left.m_it == right.m_it; }
friend bool operator!=(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
{ return left.m_it != right.m_it; }
};
template<class FwdIterator>
input_iterator_wrapper<FwdIterator> make_input_from_forward_iterator(const FwdIterator &it)
{ return input_iterator_wrapper<FwdIterator>(it); }
} //namespace test{
} //namespace container {
} //namespace boost{
#endif //BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP

View File

@@ -18,6 +18,7 @@
#include <vector>
#include <functional>
#include "print_container.hpp"
#include "input_from_forward_iterator.hpp"
#include <boost/move/move.hpp>
#include <string>
@@ -177,7 +178,20 @@ int list_test (bool copied_allocators_equal = true)
aux_vect2[i] = -1;
}
boostlist->assign(boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(&aux_vect[50]));
,boost::make_move_iterator(&aux_vect[50]));
stdlist->assign(&aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist)) return 1;
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
}
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostlist->assign(boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
stdlist->assign(&aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist)) return 1;
}
@@ -206,10 +220,36 @@ int list_test (bool copied_allocators_equal = true)
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostlist->insert(boostlist->begin()
typename MyBoostList::iterator old_begin = boostlist->begin();
typename MyBoostList::iterator it_insert =
boostlist->insert(boostlist->begin()
,boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(&aux_vect[50]));
if(it_insert != boostlist->begin() || std::distance(it_insert, old_begin) != 50)
return 1;
stdlist->insert(stdlist->begin(), &aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist))
return 1;
for(int i = 0; i < 50; ++i){
IntType move_me(-1);
aux_vect[i] = boost::move(move_me);
}
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
old_begin = boostlist->begin();
it_insert = boostlist->insert(boostlist->end()
,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
if(std::distance(it_insert, boostlist->end()) != 50)
return 1;
stdlist->insert(stdlist->end(), &aux_vect2[0], &aux_vect2[50]);
if(!CheckEqualContainers(boostlist, stdlist))
return 1;
}
boostlist->unique();

View File

@@ -73,6 +73,12 @@ class movable_int
int get_int() const
{ return m_int; }
friend bool operator==(const movable_int &l, int r)
{ return l.get_int() == r; }
friend bool operator==(int l, const movable_int &r)
{ return l == r.get_int(); }
private:
int m_int;
};
@@ -144,6 +150,12 @@ class movable_and_copyable_int
int get_int() const
{ return m_int; }
friend bool operator==(const movable_and_copyable_int &l, int r)
{ return l.get_int() == r; }
friend bool operator==(int l, const movable_and_copyable_int &r)
{ return l == r.get_int(); }
private:
int m_int;
};
@@ -202,6 +214,12 @@ class copyable_int
int get_int() const
{ return m_int; }
friend bool operator==(const copyable_int &l, int r)
{ return l.get_int() == r; }
friend bool operator==(int l, const copyable_int &r)
{ return l == r.get_int(); }
private:
int m_int;
};
@@ -256,10 +274,17 @@ class non_copymovable_int
int get_int() const
{ return m_int; }
friend bool operator==(const non_copymovable_int &l, int r)
{ return l.get_int() == r; }
friend bool operator==(int l, const non_copymovable_int &r)
{ return l == r.get_int(); }
private:
int m_int;
};
} //namespace test {
} //namespace container {
} //namespace boost {

View File

@@ -88,13 +88,13 @@ int set_test ()
IntType move_me(i);
aux_vect3[i] = boost::move(move_me);
}
/*
MyBoostSet *boostset3 = MyBoostSet
MyBoostSet *boostset3 = new MyBoostSet
( ordered_unique_range
, boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(aux_vect + 50));
MyStdSet *stdset3 = new MyStdSet(aux_vect2, aux_vect2 + 50);
MyBoostMultiSet *boostmultiset3 = MyBoostMultiSet
MyBoostMultiSet *boostmultiset3 = new MyBoostMultiSet
( ordered_range
, boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(aux_vect3 + 50));
@@ -108,15 +108,15 @@ int set_test ()
std::cout << "Error in construct<MyBoostMultiSet>(MyBoostMultiSet3)" << std::endl;
return 1;
}
*/
delete boostset2;
delete boostmultiset2;
delete stdset2;
delete stdmultiset2;
//delete boostset3;
//delete boostmultiset3;
//delete stdset3;
//delete stdmultiset3;
delete boostset3;
delete boostmultiset3;
delete stdset3;
delete stdmultiset3;
}
int i, j;

View File

@@ -8,6 +8,9 @@
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
#define BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
#include <boost/container/detail/config_begin.hpp>
#include <algorithm>
#include <memory>
@@ -24,6 +27,7 @@
#include <string>
#include <vector>
#include "emplace_test.hpp"
#include "input_from_forward_iterator.hpp"
namespace boost{
namespace container {
@@ -133,10 +137,11 @@ int vector_test()
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostvector->insert(boostvector->end()
typename MyBoostVector::iterator insert_it =
boostvector->insert(boostvector->end()
,boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(aux_vect + 50));
if(std::size_t(std::distance(insert_it, boostvector->end())) != 50) return 1;
stdvector->insert(stdvector->end(), aux_vect2, aux_vect2 + 50);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
@@ -156,9 +161,30 @@ int vector_test()
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
boostvector->insert(boostvector->begin()
typename MyBoostVector::iterator insert_it =
boostvector->insert(boostvector->begin()
,boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(aux_vect + 50));
if(boostvector->begin() != insert_it) return 1;
stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
for(int i = 0; i < 50; ++i){
IntType new_int(-1);
aux_vect[i] = boost::move(new_int);
}
for(int i = 0; i < 50; ++i){
aux_vect2[i] = -1;
}
//Now try with input iterators instead
insert_it = boostvector->insert(boostvector->begin()
// ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
// ,boost::make_move_iterator(make_input_from_forward_iterator(aux_vect + 50))
,boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(aux_vect + 50)
);
if(boostvector->begin() != insert_it) return 1;
stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
@@ -204,12 +230,20 @@ int vector_test()
//Test insertion from list
{
std::list<int> l(50, int(1));
boostvector->insert(boostvector->begin(), l.begin(), l.end());
typename MyBoostVector::iterator it_insert =
boostvector->insert(boostvector->begin(), l.begin(), l.end());
if(boostvector->begin() != it_insert) return 1;
stdvector->insert(stdvector->begin(), l.begin(), l.end());
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
boostvector->assign(l.begin(), l.end());
stdvector->assign(l.begin(), l.end());
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
boostvector->clear();
stdvector->clear();
boostvector->assign(make_input_from_forward_iterator(l.begin()), make_input_from_forward_iterator(l.end()));
stdvector->assign(l.begin(), l.end());
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
/*
std::size_t cap = boostvector->capacity();
@@ -252,3 +286,6 @@ int vector_test()
} //namespace boost{
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER