mirror of
https://github.com/boostorg/container.git
synced 2025-08-04 15:04:29 +02:00
Implemented LWG Issue #149 (range insertion now returns an iterator) & cleaned up insertion code in most containers
[SVN r80348]
This commit is contained in:
@@ -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]
|
||||
|
||||
|
@@ -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,22 +1047,60 @@ 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,28 +1211,62 @@ 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)
|
||||
|
||||
@@ -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();
|
||||
|
@@ -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 (...) {
|
||||
|
@@ -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); }
|
||||
|
@@ -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)
|
||||
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 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(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];
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert_equal(ordered_range_t, InIt first, InIt last)
|
||||
{
|
||||
typedef typename
|
||||
std::iterator_traits<InIt>::iterator_category ItCat;
|
||||
this->priv_insert_equal(ordered_range_t(), first, last, ItCat());
|
||||
//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 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());
|
||||
}
|
||||
|
||||
#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,103 +928,39 @@ 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Key, class Value, class KeyOfValue,
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
@@ -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)
|
||||
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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));
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -93,7 +93,7 @@ class clear_on_destroy
|
||||
{
|
||||
if(do_clear_){
|
||||
c_.clear();
|
||||
c_.clear_pool();
|
||||
c_.priv_clear_pool();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,9 @@ class iterator
|
||||
: 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,32 +1128,69 @@ 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)
|
||||
|
||||
@@ -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
|
||||
|
@@ -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,14 +682,20 @@ 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.
|
||||
@@ -694,8 +703,8 @@ class basic_string
|
||||
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,22 +1391,143 @@ 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()
|
||||
//!
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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");
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
@@ -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">
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
80
test/input_from_forward_iterator.hpp
Normal file
80
test/input_from_forward_iterator.hpp
Normal 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
|
@@ -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>
|
||||
|
||||
@@ -180,6 +181,19 @@ int list_test (bool copied_allocators_equal = true)
|
||||
,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;
|
||||
}
|
||||
|
||||
if(copied_allocators_equal){
|
||||
@@ -206,10 +220,36 @@ int list_test (bool copied_allocators_equal = true)
|
||||
for(int i = 0; i < 50; ++i){
|
||||
aux_vect2[i] = -1;
|
||||
}
|
||||
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();
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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));
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user