|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r80478 - in trunk: boost/container boost/container/detail libs/container/test
From: igaztanaga_at_[hidden]
Date: 2012-09-09 17:47:33
Author: igaztanaga
Date: 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
New Revision: 80478
URL: http://svn.boost.org/trac/boost/changeset/80478
Log:
Reduced template code bloat making stable_vector's index independent from value_type.
Text files modified:
trunk/boost/container/detail/destroyers.hpp | 111 ++++
trunk/boost/container/detail/multiallocation_chain.hpp | 2
trunk/boost/container/detail/node_alloc_holder.hpp | 93 ---
trunk/boost/container/stable_vector.hpp | 1017 +++++++++++++++++++++------------------
trunk/boost/container/vector.hpp | 2
trunk/libs/container/test/vector_test.hpp | 50 +
6 files changed, 694 insertions(+), 581 deletions(-)
Modified: trunk/boost/container/detail/destroyers.hpp
==============================================================================
--- trunk/boost/container/detail/destroyers.hpp (original)
+++ trunk/boost/container/detail/destroyers.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -28,6 +28,68 @@
namespace container_detail {
//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an object using a STL allocator.
+template <class A>
+struct scoped_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef container_detail::integral_constant<unsigned,
+ boost::container::container_detail::
+ version<A>::value> alloc_version;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
+
+ private:
+ void priv_deallocate(allocator_v1)
+ { m_alloc.deallocate(m_ptr, 1); }
+
+ void priv_deallocate(allocator_v2)
+ { m_alloc.deallocate_one(m_ptr); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
+
+ public:
+
+ pointer m_ptr;
+ A& m_alloc;
+
+ scoped_deallocator(pointer p, A& a)
+ : m_ptr(p), m_alloc(a)
+ {}
+
+ ~scoped_deallocator()
+ { if (m_ptr)priv_deallocate(alloc_version()); }
+
+ scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
+ : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
+ { o.release(); }
+
+ pointer get() const
+ { return m_ptr; }
+
+ void release()
+ { m_ptr = 0; }
+};
+
+template <class Allocator>
+struct null_scoped_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_deallocator(pointer, Allocator&, size_type)
+ {}
+
+ void release()
+ {}
+
+ pointer get() const
+ { return pointer(); }
+};
+
+//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
@@ -239,10 +301,57 @@
void operator()(const pointer &p)
{
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
- priv_deallocate(p, alloc_version());
+ this->priv_deallocate(p, alloc_version());
}
};
+template <class A>
+class allocator_destroyer_and_chain_builder
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+
+ A & a_;
+ multiallocation_chain &c_;
+
+ public:
+ allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
+ : a_(a), c_(c)
+ {}
+
+ void operator()(const typename A::pointer &p)
+ {
+ allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
+ c_.push_front(p);
+ }
+};
+
+template <class A>
+class allocator_multialloc_chain_node_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+ typedef allocator_destroyer_and_chain_builder<A> chain_builder;
+
+ A & a_;
+ multiallocation_chain c_;
+
+ public:
+ allocator_multialloc_chain_node_deallocator(A &a)
+ : a_(a), c_()
+ {}
+
+ chain_builder get_chain_builder()
+ { return chain_builder(a_, c_); }
+
+ ~allocator_multialloc_chain_node_deallocator()
+ {
+ if(!c_.empty())
+ a_.deallocate_individual(boost::move(c_));
+ }
+};
} //namespace container_detail {
} //namespace container {
Modified: trunk/boost/container/detail/multiallocation_chain.hpp
==============================================================================
--- trunk/boost/container/detail/multiallocation_chain.hpp (original)
+++ trunk/boost/container/detail/multiallocation_chain.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -200,7 +200,7 @@
void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, size_type n)
{ holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
- void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n)
+ void incorporate_after(iterator after_this, pointer begin, pointer before_end, size_type n)
{ holder_.incorporate_after(after_this.base(), begin, before_end, n); }
void pop_front()
Modified: trunk/boost/container/detail/node_alloc_holder.hpp
==============================================================================
--- trunk/boost/container/detail/node_alloc_holder.hpp (original)
+++ trunk/boost/container/detail/node_alloc_holder.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -43,99 +43,6 @@
namespace container {
namespace container_detail {
-//!A deleter for scoped_ptr that deallocates the memory
-//!allocated for an object using a STL allocator.
-template <class A>
-struct scoped_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::pointer pointer;
- typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::
- version<A>::value> alloc_version;
- typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
- typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
-
- private:
- void priv_deallocate(allocator_v1)
- { m_alloc.deallocate(m_ptr, 1); }
-
- void priv_deallocate(allocator_v2)
- { m_alloc.deallocate_one(m_ptr); }
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
-
- public:
-
- pointer m_ptr;
- A& m_alloc;
-
- scoped_deallocator(pointer p, A& a)
- : m_ptr(p), m_alloc(a)
- {}
-
- ~scoped_deallocator()
- { if (m_ptr)priv_deallocate(alloc_version()); }
-
- scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
- : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
- { o.release(); }
-
- pointer get() const
- { return m_ptr; }
-
- void release()
- { m_ptr = 0; }
-};
-
-template <class A>
-class allocator_destroyer_and_chain_builder
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
-
- A & a_;
- multiallocation_chain &c_;
-
- public:
- allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
- : a_(a), c_(c)
- {}
-
- void operator()(const typename A::pointer &p)
- {
- allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
- c_.push_front(p);
- }
-};
-
-template <class A>
-class allocator_multialloc_chain_node_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
- typedef allocator_destroyer_and_chain_builder<A> chain_builder;
-
- A & a_;
- multiallocation_chain c_;
-
- public:
- allocator_multialloc_chain_node_deallocator(A &a)
- : a_(a), c_()
- {}
-
- chain_builder get_chain_builder()
- { return chain_builder(a_, c_); }
-
- ~allocator_multialloc_chain_node_deallocator()
- {
- if(!c_.empty())
- a_.deallocate_individual(boost::move(c_));
- }
-};
-
template<class ValueCompare, class Node>
struct node_compare
: private ValueCompare
Modified: trunk/boost/container/stable_vector.hpp
==============================================================================
--- trunk/boost/container/stable_vector.hpp (original)
+++ trunk/boost/container/stable_vector.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -28,6 +28,7 @@
#include <boost/container/container_fwd.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
+#include <boost/assert.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
@@ -48,10 +49,6 @@
//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
-#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
-#include <boost/assert.hpp>
-#endif
-
///@endcond
namespace boost {
@@ -61,24 +58,6 @@
namespace stable_vector_detail{
-template<class SmartPtr>
-struct smart_ptr_type
-{
- typedef typename SmartPtr::value_type value_type;
- typedef value_type *pointer;
- static pointer get (const SmartPtr &smartptr)
- { return smartptr.get();}
-};
-
-template<class T>
-struct smart_ptr_type<T*>
-{
- typedef T value_type;
- typedef value_type *pointer;
- static pointer get (pointer ptr)
- { return ptr;}
-};
-
template <class C>
class clear_on_destroy
{
@@ -108,22 +87,21 @@
template<typename VoidPointer, typename T>
struct node;
-template<class NodePtr>
+template<class VoidPtr>
struct node_base
{
private:
- typedef NodePtr node_ptr;
typedef typename boost::intrusive::
- pointer_traits<node_ptr> node_ptr_traits;
- typedef typename node_ptr_traits::
+ pointer_traits<VoidPtr> void_ptr_traits;
+ typedef typename void_ptr_traits::
template rebind_pointer
<node_base>::type node_base_ptr;
- typedef typename node_ptr_traits::
+ typedef typename void_ptr_traits::
template rebind_pointer
- <node_ptr>::type node_ptr_ptr;
+ <node_base_ptr>::type node_base_ptr_ptr;
public:
- node_base(const node_ptr_ptr &n)
+ node_base(const node_base_ptr_ptr &n)
: up(n)
{}
@@ -131,15 +109,12 @@
: up()
{}
- node_ptr_ptr up;
+ node_base_ptr_ptr up;
};
template<typename VoidPointer, typename T>
struct node
- : public node_base
- <typename boost::intrusive::
- pointer_traits<VoidPointer>::template
- rebind_pointer< node<VoidPointer, T> >::type>
+ : public node_base<VoidPointer>
{
private:
node();
@@ -162,10 +137,15 @@
typedef typename ptr_traits::template
rebind_pointer<void>::type void_ptr;
typedef node<void_ptr, T> node_type;
+ typedef node_base<void_ptr> node_base_type;
typedef typename ptr_traits::template
rebind_pointer<node_type>::type node_ptr;
+ typedef boost::intrusive::
+ pointer_traits<node_ptr> node_ptr_traits;
typedef typename ptr_traits::template
- rebind_pointer<node_ptr>::type node_ptr_ptr;
+ rebind_pointer<node_base_type>::type node_base_ptr;
+ typedef typename ptr_traits::template
+ rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
typedef typename ptr_traits::template
rebind_pointer<T>::type friend_iterator_pointer;
@@ -189,20 +169,26 @@
: pn(x.pn)
{}
+ node_ptr &node_pointer()
+ { return pn; }
+
+ const node_ptr &node_pointer() const
+ { return pn; }
+
public:
//Pointer like operators
reference operator*() const
{ return pn->value; }
pointer operator->() const
- { return ptr_traits::pointer_to(*this); }
+ { return ptr_traits::pointer_to(this->operator*()); }
//Increment / Decrement
- iterator& operator++()
+ iterator& operator++()
{
- if(node_ptr_ptr p = this->pn->up){
+ if(node_base_ptr_ptr p = this->pn->up){
++p;
- this->pn = *p;
+ this->pn = node_ptr_traits::static_cast_from(*p);
}
return *this;
}
@@ -212,9 +198,9 @@
iterator& operator--()
{
- if(node_ptr_ptr p = this->pn->up){
+ if(node_base_ptr_ptr p = this->pn->up){
--p;
- this->pn = *p;
+ this->pn = node_ptr_traits::static_cast_from(*p);
}
return *this;
}
@@ -231,9 +217,9 @@
iterator& operator+=(difference_type off)
{
- if(node_ptr_ptr p = this->pn->up){
+ if(node_base_ptr_ptr p = this->pn->up){
p += off;
- this->pn = *p;
+ this->pn = node_ptr_traits::static_cast_from(*p);
}
return *this;
}
@@ -309,39 +295,131 @@
, typename allocator_traits<A>::value_type> type;
};
+template<class VoidPtr, class VoidAllocator>
+struct index_traits
+{
+ typedef boost::intrusive::
+ pointer_traits
+ <VoidPtr> void_ptr_traits;
+ typedef stable_vector_detail::
+ node_base<VoidPtr> node_base_type;
+ typedef typename void_ptr_traits::template
+ rebind_pointer<node_base_type>::type node_base_ptr;
+ typedef typename void_ptr_traits::template
+ rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
+ typedef boost::intrusive::
+ pointer_traits<node_base_ptr> node_base_ptr_traits;
+ typedef boost::intrusive::
+ pointer_traits<node_base_ptr_ptr> node_base_ptr_ptr_traits;
+ typedef typename allocator_traits<VoidAllocator>::
+ template portable_rebind_alloc
+ <node_base_ptr>::type node_base_ptr_allocator;
+ typedef ::boost::container::vector
+ <node_base_ptr, node_base_ptr_allocator> index_type;
+ typedef typename index_type::iterator index_iterator;
+ typedef typename index_type::const_iterator const_index_iterator;
+ typedef typename index_type::size_type size_type;
+
+ static const size_type ExtraPointers = 3;
+ //Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
+ // back() is this->index.back() - ExtraPointers;
+ // end node index is *(this->index.end() -3)
+ // Node cache first is *(this->index.end() - 2);
+ // Node cache last is this->index.back();
+
+ static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
+ { return node_base_ptr_ptr_traits::pointer_to(n); }
+
+ static void fix_up_pointers(index_iterator first, index_iterator last)
+ {
+ while(first != last){
+ typedef typename index_type::reference node_base_ptr_ref;
+ node_base_ptr_ref nbp = *first;
+ nbp->up = index_traits::ptr_to_node_base_ptr(nbp);
+ ++first;
+ }
+ }
+
+ static index_iterator get_fix_up_end(index_type &index)
+ { return index.end() - (ExtraPointers - 1); }
+
+ static void fix_up_pointers_from(index_type & index, index_iterator first)
+ { index_traits::fix_up_pointers(first, index_traits::get_fix_up_end(index)); }
+
+ static void readjust_end_node(index_type &index, node_base_type &end_node)
+ {
+ if(!index.empty()){
+ node_base_ptr &end_node_idx_ref = *(--index_traits::get_fix_up_end(index));
+ end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
+ end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
+ }
+ else{
+ end_node.up = node_base_ptr_ptr();
+ }
+ }
+
+ static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
+ {
+ if(index.empty()){
+ index.reserve(index_capacity_if_empty + ExtraPointers);
+ index.resize(ExtraPointers);
+ node_base_ptr &end_node_ref = *index.data();
+ end_node_ref = node_base_ptr_traits::pointer_to(end_node);
+ end_node.up = index_traits::ptr_to_node_base_ptr(end_node_ref);
+ }
+ }
+
+
+ #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+ static bool invariants(index_type &index)
+ {
+ for( index_iterator it = index.begin()
+ , it_end = index_traits::get_fix_up_end(index)
+ ; it != it_end
+ ; ++it){
+ if((*it)->up != index_traits::ptr_to_node_base_ptr(*it)){
+ return false;
+ }
+ }
+ return true;
+ }
+ #endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+};
+
} //namespace stable_vector_detail
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+
+ #define STABLE_VECTOR_CHECK_INVARIANT \
+ invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
+ BOOST_JOIN(check_invariant_,__LINE__).touch();
-#define STABLE_VECTOR_CHECK_INVARIANT \
-invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
-BOOST_JOIN(check_invariant_,__LINE__).touch();
-#else
+ #else //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
-#define STABLE_VECTOR_CHECK_INVARIANT
+ #define STABLE_VECTOR_CHECK_INVARIANT
-#endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
#endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
/// @endcond
-//! Originally developed by Joaquin M. Lopez Munoz, stable_vector is std::vector
+//! Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector
//! drop-in replacement implemented as a node container, offering iterator and reference
//! stability.
//!
-//! More details taken the author's blog:
+//! Here are the details taken from the author's blog
//! (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" >
-//! Introducing stable_vector</a>)
+//! Introducing stable_vector</a>):
//!
//! We present stable_vector, a fully STL-compliant stable container that provides
//! most of the features of std::vector except element contiguity.
//!
//! General properties: stable_vector satisfies all the requirements of a container,
//! a reversible container and a sequence and provides all the optional operations
-//! present in std::vector. Like std::vector, iterators are random access.
+//! present in std::vector. Like std::vector, iterators are random access.
//! stable_vector does not provide element contiguity; in exchange for this absence,
//! the container is stable, i.e. references and iterators to an element of a stable_vector
//! remain valid as long as the element is not erased, and an iterator that has been
@@ -358,7 +436,7 @@
//! additional allocation per element.
//!
//! Exception safety: As stable_vector does not internally copy elements around, some
-//! operations provide stronger exception safety guarantees than in std::vector:
+//! operations provide stronger exception safety guarantees than in std::vector.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class T, class A = std::allocator<T> >
#else
@@ -368,34 +446,43 @@
{
///@cond
typedef allocator_traits<A> allocator_traits_type;
+ typedef typename boost::intrusive::pointer_traits
+ <typename allocator_traits_type::pointer>::
+ template rebind_pointer<void>::type void_ptr;
+ typedef typename allocator_traits_type::
+ template portable_rebind_alloc
+ <void>::type void_allocator_type;
+ typedef stable_vector_detail::index_traits
+ <void_ptr, void_allocator_type> index_traits_type;
+ typedef typename index_traits_type::node_base_type node_base_type;
+ typedef typename index_traits_type::node_base_ptr node_base_ptr;
+ typedef typename index_traits_type::
+ node_base_ptr_ptr node_base_ptr_ptr;
+ typedef typename index_traits_type::
+ node_base_ptr_traits node_base_ptr_traits;
+ typedef typename index_traits_type::
+ node_base_ptr_ptr_traits node_base_ptr_ptr_traits;
+ typedef typename index_traits_type::index_type index_type;
+ typedef typename index_traits_type::index_iterator index_iterator;
+ typedef typename index_traits_type::
+ const_index_iterator const_index_iterator;
+
typedef typename container_detail::
move_const_ref_type<T>::type insert_const_ref_type;
typedef boost::intrusive::
pointer_traits
<typename allocator_traits_type::pointer> ptr_traits;
- typedef typename boost::intrusive::pointer_traits
- <typename allocator_traits_type::pointer>::
- template rebind_pointer<void>::type void_ptr;
typedef stable_vector_detail::node<void_ptr, T> node_type;
typedef typename ptr_traits::template
rebind_pointer<node_type>::type node_ptr;
- typedef typename ptr_traits::template
- rebind_pointer<node_ptr>::type node_ptr_ptr;
- typedef stable_vector_detail::
- node_base<node_ptr> node_base_type;
- typedef typename ptr_traits::template
- rebind_pointer<node_base_type>::type node_base_ptr;
- typedef boost::intrusive::
- pointer_traits<node_base_ptr> node_base_ptr_traits;
typedef boost::intrusive::
pointer_traits<node_ptr> node_ptr_traits;
+ typedef typename ptr_traits::template
+ rebind_pointer<const node_type>::type const_node_ptr;
typedef boost::intrusive::
- pointer_traits<node_ptr_ptr> node_ptr_ptr_traits;
- typedef ::boost::container::vector<node_ptr,
- typename allocator_traits_type::
- template portable_rebind_alloc
- <node_ptr>::type> impl_type;
- typedef typename impl_type::iterator impl_iterator;
+ pointer_traits<const_node_ptr> const_node_ptr_traits;
+ typedef typename node_ptr_traits::reference node_reference;
+ typedef typename const_node_ptr_traits::reference const_node_reference;
typedef ::boost::container::container_detail::
integral_constant<unsigned, 1> allocator_v1;
@@ -407,6 +494,11 @@
typedef typename allocator_traits_type::
template portable_rebind_alloc
<node_type>::type node_allocator_type;
+ typedef typename stable_vector_detail::
+ select_multiallocation_chain
+ < node_allocator_type
+ , alloc_version::value
+ >::type multiallocation_chain;
node_ptr allocate_one()
{ return this->allocate_one(alloc_version()); }
@@ -442,6 +534,74 @@
::value>::type * = 0)
{ this->priv_node_alloc().deallocate_one(p); }
+ multiallocation_chain allocate_individual(typename allocator_traits_type::size_type n)
+ { return this->allocate_individual(n, alloc_version()); }
+
+ struct allocate_individual_rollback
+ {
+ allocate_individual_rollback(stable_vector &sv, multiallocation_chain &chain)
+ : mr_sv(sv), mr_chain(chain)
+ {}
+
+ ~allocate_individual_rollback()
+ {
+ if(!mr_chain.empty()){
+ mr_sv.deallocate_individual(mr_chain);
+ }
+ }
+
+ stable_vector &mr_sv;
+ multiallocation_chain &mr_chain;
+ };
+
+ template<class AllocatorVersion>
+ multiallocation_chain allocate_individual
+ (typename allocator_traits_type::size_type n, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ multiallocation_chain m;
+ multiallocation_chain m_ret;
+ allocate_individual_rollback rollback(*this, m);
+ while(n--){
+ m.push_front(this->allocate_one());
+ }
+ m.swap(m_ret);
+ return ::boost::move(m_ret);
+ }
+
+ template<class AllocatorVersion>
+ multiallocation_chain allocate_individual
+ (typename allocator_traits_type::size_type n, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { return this->priv_node_alloc().allocate_individual(n); }
+
+ void deallocate_individual(multiallocation_chain &holder)
+ { this->deallocate_individual(holder, alloc_version()); }
+
+ template<class AllocatorVersion>
+ void deallocate_individual(multiallocation_chain & holder, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ while(!holder.empty()){
+ const node_ptr n = holder.front();
+ holder.pop_front();
+ this->deallocate_one(n);
+ }
+ }
+
+ template<class AllocatorVersion>
+ void deallocate_individual(multiallocation_chain & holder, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { this->priv_node_alloc().deallocate_individual(boost::move(holder)); }
+
friend class stable_vector_detail::clear_on_destroy<stable_vector>;
///@endcond
public:
@@ -457,7 +617,7 @@
<T,T&, pointer> iterator;
typedef stable_vector_detail::iterator
<T,const T&, const_pointer> const_iterator;
- typedef typename impl_type::size_type size_type;
+ typedef typename index_type::size_type size_type;
typedef typename iterator::difference_type difference_type;
typedef T value_type;
typedef A allocator_type;
@@ -468,19 +628,15 @@
///@cond
private:
BOOST_COPYABLE_AND_MOVABLE(stable_vector)
- static const size_type ExtraPointers = 3;
- //This container stores metadata at the end of the node_ptr vector with additional 3 pointers:
- // back() is this->impl.back() - ExtraPointers;
- // end node index is *(this->impl.end() -3)
- // Node cache first is *(this->impl.end() - 2);
- // Node cache last is this->impl.back();
+ static const size_type ExtraPointers = index_traits_type::ExtraPointers;
- typedef typename stable_vector_detail::
- select_multiallocation_chain
- < node_allocator_type
- , alloc_version::value
- >::type multiallocation_chain;
+ class insert_rollback;
+ friend class insert_rollback;
+
+ class push_back_rollback;
+ friend class push_back_rollback;
///@endcond
+
public:
//! <b>Effects</b>: Default constructs a stable_vector.
@@ -489,7 +645,7 @@
//!
//! <b>Complexity</b>: Constant.
stable_vector()
- : internal_data(), impl()
+ : internal_data(), index()
{
STABLE_VECTOR_CHECK_INVARIANT;
}
@@ -500,7 +656,7 @@
//!
//! <b>Complexity</b>: Constant.
explicit stable_vector(const allocator_type& al)
- : internal_data(al), impl(al)
+ : internal_data(al), index(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
}
@@ -513,7 +669,7 @@
//!
//! <b>Complexity</b>: Linear to n.
explicit stable_vector(size_type n)
- : internal_data(), impl()
+ : internal_data(), index()
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->resize(n);
@@ -529,7 +685,7 @@
//!
//! <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), index(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cend(), n, t);
@@ -546,7 +702,7 @@
//! <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), index(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cend(), first, last);
@@ -562,8 +718,8 @@
stable_vector(const stable_vector& x)
: internal_data(allocator_traits<node_allocator_type>::
select_on_container_copy_construction(x.priv_node_alloc()))
- , impl(allocator_traits<allocator_type>::
- select_on_container_copy_construction(x.impl.get_stored_allocator()))
+ , index(allocator_traits<allocator_type>::
+ select_on_container_copy_construction(x.index.get_stored_allocator()))
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cend(), x.begin(), x.end());
@@ -577,7 +733,7 @@
//!
//! <b>Complexity</b>: Constant.
stable_vector(BOOST_RV_REF(stable_vector) x)
- : internal_data(boost::move(x.priv_node_alloc())), impl(boost::move(x.impl))
+ : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
{
this->priv_swap_members(x);
}
@@ -588,7 +744,7 @@
//!
//! <b>Complexity</b>: Linear to the elements x contains.
stable_vector(const stable_vector& x, const allocator_type &a)
- : internal_data(a), impl(a)
+ : internal_data(a), index(a)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->insert(this->cend(), x.begin(), x.end());
@@ -603,7 +759,7 @@
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
- : internal_data(a), impl(a)
+ : internal_data(a), index(a)
{
if(this->priv_node_alloc() == x.priv_node_alloc()){
this->priv_swap_members(x);
@@ -625,7 +781,7 @@
~stable_vector()
{
this->clear();
- priv_clear_pool();
+ this->priv_clear_pool();
}
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -649,7 +805,7 @@
this->shrink_to_fit();
}
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);
+ container_detail::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
this->assign(x.begin(), x.end());
}
return *this;
@@ -672,7 +828,7 @@
if(this_alloc == x_alloc){
//Destroy objects but retain memory
this->clear();
- this->impl = boost::move(x.impl);
+ this->index = boost::move(x.index);
this->priv_swap_members(x);
//Move allocator if needed
container_detail::bool_<allocator_traits_type::
@@ -716,13 +872,12 @@
}
}
-
//! <b>Effects</b>: Assigns the n copies of val to *this.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- void assign(size_type n,const T& t)
+ void assign(size_type n, const T& t)
{
typedef constant_iterator<value_type, difference_type> cvalue_iterator;
this->assign(cvalue_iterator(t, n), cvalue_iterator());
@@ -733,7 +888,7 @@
//! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
- allocator_type get_allocator()const
+ allocator_type get_allocator() const
{ return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
@@ -762,7 +917,7 @@
//!
//! <b>Complexity</b>: Constant.
iterator begin()
- { return (this->impl.empty()) ? this->end(): iterator(this->impl.front()) ; }
+ { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
//!
@@ -770,21 +925,23 @@
//!
//! <b>Complexity</b>: Constant.
const_iterator begin()const
- { return (this->impl.empty()) ? this->cend() : const_iterator(this->impl.front()) ; }
+ { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
//! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end() {return iterator(this->get_end_node());}
+ iterator end()
+ { return iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end()const {return const_iterator(this->get_end_node());}
+ const_iterator end() const
+ { return const_iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -792,7 +949,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin() {return reverse_iterator(this->end());}
+ reverse_iterator rbegin()
+ { return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -800,7 +958,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin()const {return const_reverse_iterator(this->end());}
+ const_reverse_iterator rbegin() const
+ { return const_reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -808,7 +967,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend() {return reverse_iterator(this->begin());}
+ reverse_iterator rend()
+ { return reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -816,21 +976,24 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend()const {return const_reverse_iterator(this->begin());}
+ const_reverse_iterator rend()const
+ { return const_reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin()const {return this->begin();}
+ const_iterator cbegin() const
+ { return this->begin(); }
//! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend()const {return this->end();}
+ const_iterator cend()const
+ { return this->end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -838,7 +1001,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin()const{return this->rbegin();}
+ const_reverse_iterator crbegin() const
+ { return this->rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -846,7 +1010,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend()const {return this->rend();}
+ const_reverse_iterator crend()const
+ { return this->rend(); }
//! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
//!
@@ -854,7 +1019,10 @@
//!
//! <b>Complexity</b>: Constant.
size_type size() const
- { return this->impl.empty() ? 0 : (this->impl.size() - ExtraPointers); }
+ {
+ const size_type index_size = this->index.size();
+ return index_size ? (index_size - ExtraPointers) : 0;
+ }
//! <b>Effects</b>: Returns the largest possible size of the stable_vector.
//!
@@ -862,7 +1030,7 @@
//!
//! <b>Complexity</b>: Constant.
size_type max_size() const
- { return this->impl.max_size() - ExtraPointers; }
+ { return this->index.max_size() - ExtraPointers; }
//! <b>Effects</b>: Number of elements for which memory has been allocated.
//! capacity() is always greater than or equal to size().
@@ -872,14 +1040,13 @@
//! <b>Complexity</b>: Constant.
size_type capacity() const
{
- if(!this->impl.capacity()){
- return 0;
- }
- else{
- const size_type num_nodes = this->impl.size() + this->internal_data.pool_size;
- const size_type num_buck = this->impl.capacity();
- return (num_nodes < num_buck) ? num_nodes : num_buck;
- }
+ const size_type index_size = this->index.size();
+ BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
+ const size_type bucket_extra_capacity = this->index.capacity()- index_size;
+ const size_type node_extra_capacity = this->internal_data.pool_size;
+ const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
+ ? bucket_extra_capacity : node_extra_capacity;
+ return (index_size ? (index_size - ExtraPointers + extra_capacity) : index_size);
}
//! <b>Effects</b>: Returns true if the stable_vector contains no elements.
@@ -888,7 +1055,7 @@
//!
//! <b>Complexity</b>: Constant.
bool empty() const
- { return this->impl.empty() || this->impl.size() == ExtraPointers; }
+ { return this->index.size() <= ExtraPointers; }
//! <b>Effects</b>: Inserts or erases elements at the end such that
//! the size becomes n. New elements are copy constructed from x.
@@ -933,20 +1100,20 @@
if(n > this->max_size())
throw std::bad_alloc();
- size_type size = this->size();
+ size_type size = this->size();
size_type old_capacity = this->capacity();
if(n > old_capacity){
- this->initialize_end_node(n);
- const void * old_ptr = &impl[0];
- this->impl.reserve(n + ExtraPointers);
- bool realloced = &impl[0] != old_ptr;
+ index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
+ const void * old_ptr = &index[0];
+ this->index.reserve(n + ExtraPointers);
+ bool realloced = &index[0] != old_ptr;
//Fix the pointers for the newly allocated buffer
if(realloced){
- this->align_nodes(this->impl.begin(), this->impl.begin()+size+1);
+ index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
}
//Now fill pool if data is not enough
if((n - size) > this->internal_data.pool_size){
- this->priv_add_to_pool((n - size) - this->internal_data.pool_size);
+ this->priv_increase_pool((n - size) - this->internal_data.pool_size);
}
}
}
@@ -960,7 +1127,7 @@
//!
//! <b>Complexity</b>: Constant.
reference operator[](size_type n)
- { return this->impl[n]->value; }
+ { return static_cast<node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
//!
@@ -971,7 +1138,7 @@
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n)const
- { return this->impl[n]->value; }
+ { return static_cast<const_node_reference>(*this->index[n]).value; }
//! <b>Requires</b>: size() > n.
//!
@@ -1012,7 +1179,7 @@
//!
//! <b>Complexity</b>: Constant.
reference front()
- { return this->impl.front()->value; }
+ { return static_cast<node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1022,8 +1189,8 @@
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference front()const
- { return this->impl.front()->value; }
+ const_reference front() const
+ { return static_cast<const_node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1034,7 +1201,7 @@
//!
//! <b>Complexity</b>: Constant.
reference back()
- { return (*(&this->impl.back() - ExtraPointers))->value; }
+ { return static_cast<node_reference>(*this->index[this->size() - ExtraPointers]).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1045,25 +1212,16 @@
//!
//! <b>Complexity</b>: Constant.
const_reference back()const
- { return (*(&this->impl.back() - ExtraPointers))->value; }
+ { return static_cast<const_node_reference>(*this->index[this->size() - ExtraPointers]).value; }
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
//!
//! <b>Throws</b>: If memory allocation throws or
//! T's copy constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time.
- void push_back(insert_const_ref_type x)
- { return priv_push_back(x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- void push_back(T &x) { push_back(const_cast<const T &>(x)); }
-
- template<class U>
- void push_back(const U &u, typename container_detail::enable_if_c
- <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_push_back(u); }
- #endif
+ void push_back(const T &x);
//! <b>Effects</b>: Constructs a new element in the end of the stable_vector
//! and moves the resources of mx to this new element.
@@ -1071,8 +1229,10 @@
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: Amortized constant time.
- void push_back(BOOST_RV_REF(T) t)
- { this->insert(end(), boost::move(t)); }
+ void push_back(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ #endif
//! <b>Effects</b>: Removes the last element from the stable_vector.
//!
@@ -1082,6 +1242,9 @@
void pop_back()
{ this->erase(this->end()-1); }
+
+
+ #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.
@@ -1092,17 +1255,7 @@
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
//! Linear time otherwise.
- iterator insert(const_iterator position, insert_const_ref_type x)
- { return this->priv_insert(position, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c
- <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return this->priv_insert(position, u); }
- #endif
+ iterator insert(const_iterator position, const T &x);
//! <b>Requires</b>: position must be a valid iterator of *this.
//!
@@ -1114,17 +1267,10 @@
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
//! Linear time otherwise.
- iterator insert(const_iterator position, BOOST_RV_REF(T) x)
- {
- typedef repeat_iterator<T, difference_type> repeat_it;
- typedef boost::move_iterator<repeat_it> repeat_move_it;
- //Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
- this->insert(position
- ,repeat_move_it(repeat_it(x, 1))
- ,repeat_move_it(repeat_it()));
- return iterator(this->begin() + pos_n);
- }
+ iterator insert(const_iterator position, T &&x);
+ #else
+ 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.
//!
@@ -1179,16 +1325,35 @@
>::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(this->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, this->get_end_align());
+ const size_type num_new = (size_type)std::distance(first,last);
+ const size_type pos = static_cast<size_type>(position - this->cbegin());
+ if(num_new){
+ //Fills the node pool and inserts num_new null pointers in pos.
+ //If a new buffer was needed fixes up pointers up to pos so
+ //past-new nodes are not aligned until the end of this function
+ //or in a rollback in case of exception
+ index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(pos, num_new));
+ const index_iterator it_past_new(it_past_newly_constructed + num_new);
+ {
+ //Prepare rollback
+ insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
+ while(first != last){
+ const node_ptr p = this->priv_get_from_pool();
+ BOOST_ASSERT(!!p);
+ //Put it in the index so rollback can return it in pool if construct_in_place throws
+ *it_past_newly_constructed = p;
+ //Constructs and fixes up pointers This can throw
+ this->priv_build_node_from_it(p, it_past_newly_constructed, first);
+ ++first;
+ ++it_past_newly_constructed;
+ }
+ //rollback.~insert_rollback() called in case of exception
+ }
+ //Fix up pointers for past-new nodes (new nodes were fixed during construction) and
+ //nodes before insertion position in priv_insert_forward_non_templated(...)
+ index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
}
- return this->begin() + d;
+ return this->begin() + pos;
}
#endif
@@ -1277,10 +1442,10 @@
{
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d = position - this->cbegin();
- impl_iterator it = this->impl.begin() + d;
- this->delete_node(*it);
- it = this->impl.erase(it);
- this->align_nodes(it, this->get_end_align());
+ index_iterator it = this->index.begin() + d;
+ this->priv_delete_node(position.node_pointer());
+ it = this->index.erase(it);
+ index_traits_type::fix_up_pointers_from(this->index, it);
return this->begin()+d;
}
@@ -1295,11 +1460,12 @@
STABLE_VECTOR_CHECK_INVARIANT;
difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
if(d1 != d2){
- impl_iterator it1(this->impl.begin() + d1), it2(this->impl.begin() + d2);
- for(impl_iterator it = it1; it != it2; ++it)
- this->delete_node(*it);
- impl_iterator e = this->impl.erase(it1, it2);
- this->align_nodes(e, this->get_end_align());
+ index_iterator it1(this->index.begin() + d1), it2(it1 + (d2 - d1));
+ for(index_iterator it = it1; it != it2; ++it){
+ this->priv_delete_node(node_ptr_traits::static_cast_from(*it));
+ }
+ const index_iterator e = this->index.erase(it1, it2);
+ index_traits_type::fix_up_pointers_from(this->index, e);
}
return iterator(this->begin() + d1);
}
@@ -1315,7 +1481,7 @@
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> 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->index.swap(x.index);
this->priv_swap_members(x);
}
@@ -1340,19 +1506,18 @@
this->priv_clear_pool();
//If empty completely destroy the index, let's recover default-constructed state
if(this->empty()){
- this->impl.clear();
- this->impl.shrink_to_fit();
- this->internal_data.end_node.up = node_ptr_ptr();
+ this->index.clear();
+ this->index.shrink_to_fit();
+ this->internal_data.end_node.up = node_base_ptr_ptr();
}
//Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
else{
- const size_type size = this->size();
- const void* old_ptr = &impl[0];
- this->impl.shrink_to_fit();
- bool realloced = &impl[0] != old_ptr;
+ const void* old_ptr = &index[0];
+ this->index.shrink_to_fit();
+ bool realloced = &index[0] != old_ptr;
//Fix the pointers for the newly allocated buffer
if(realloced){
- this->align_nodes(this->impl.begin(), this->impl.begin()+size+1);
+ index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
}
}
}
@@ -1360,88 +1525,144 @@
/// @cond
- iterator priv_insert(const_iterator position, const value_type &t)
+ private:
+
+ class insert_rollback
{
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- return this->insert(position, cvalue_iterator(t, 1), cvalue_iterator());
- }
+ public:
- void priv_push_back(const value_type &t)
- { this->insert(end(), t); }
+ insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
+ : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
+ {}
- template<class 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)
+ ~insert_rollback()
+ {
+ if(m_it_past_constructed != m_it_past_new){
+ m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
+ index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
+ index_traits_type::fix_up_pointers_from(m_sv.index, e);
+ }
+ }
+
+ private:
+ stable_vector &m_sv;
+ index_iterator &m_it_past_constructed;
+ const index_iterator &m_it_past_new;
+ };
+
+ class push_back_rollback
{
- if(!this->impl.empty() && this->impl.back()){
- node_ptr &pool_first_ref = *(this->impl.end() - 2);
- node_ptr &pool_last_ref = this->impl.back();
+ public:
+ push_back_rollback(stable_vector &sv, const node_ptr &p)
+ : m_sv(sv), m_p(p)
+ {}
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, this->internal_data.pool_size);
- while(!holder.empty()){
- node_ptr n = holder.front();
- holder.pop_front();
- this->deallocate_one(n);
+ ~push_back_rollback()
+ {
+ if(m_p){
+ m_sv.priv_put_in_pool(m_p);
}
- pool_first_ref = pool_last_ref = 0;
- this->internal_data.pool_size = 0;
}
+
+ void release()
+ { m_p = node_ptr(); }
+
+ private:
+ stable_vector &m_sv;
+ node_ptr m_p;
+ };
+
+ index_iterator priv_insert_forward_non_templated(size_type pos, size_type num_new)
+ {
+ index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
+
+ //Now try to fill the pool with new data
+ if(this->internal_data.pool_size < num_new){
+ this->priv_increase_pool(num_new - this->internal_data.pool_size);
+ }
+
+ //Now try to make room in the vector
+ const node_base_ptr_ptr old_buffer = this->index.data();
+ this->index.insert(this->index.begin() + pos, num_new, node_ptr());
+ bool new_buffer = this->index.data() != old_buffer;
+
+ //Fix the pointers for the newly allocated buffer
+ const index_iterator index_beg = this->index.begin();
+ if(new_buffer){
+ index_traits_type::fix_up_pointers(index_beg, index_beg + pos);
+ }
+ return index_beg + pos;
}
- template<class 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)
+ bool priv_capacity_bigger_than_size() const
{
- if(!this->impl.empty() && this->impl.back()){
- node_ptr &pool_first_ref = *(this->impl.end() - 2);
- node_ptr &pool_last_ref = this->impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- this->priv_node_alloc().deallocate_individual(boost::move(holder));
- pool_first_ref = pool_last_ref = 0;
- this->internal_data.pool_size = 0;
+ return this->index.capacity() > this->index.size() &&
+ this->internal_data.pool_size > 0;
+ }
+
+ template <class U>
+ void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
+ {
+ if(this->priv_capacity_bigger_than_size()){
+ //Enough memory in the pool and in the index
+ const node_ptr p = this->priv_get_from_pool();
+ BOOST_ASSERT(!!p);
+ {
+ push_back_rollback rollback(*this, p);
+ //This might throw
+ this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
+ rollback.release();
+ }
+ //This can't throw as there is room for a new elements in the index
+ index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
+ index_traits_type::fix_up_pointers_from(this->index, new_index);
+ }
+ else{
+ this->insert(this->cend(), ::boost::forward<U>(x));
}
}
- void priv_clear_pool()
+ iterator priv_insert(const_iterator position, const value_type &t)
{
- this->priv_clear_pool(alloc_version());
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(position, cvalue_iterator(t, 1), cvalue_iterator());
}
- void priv_add_to_pool(size_type n)
+ iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x)
{
- this->priv_add_to_pool(n, alloc_version());
+ typedef repeat_iterator<T, difference_type> repeat_it;
+ typedef boost::move_iterator<repeat_it> repeat_move_it;
+ //Just call more general insert(pos, size, value) and return iterator
+ return this->insert(position, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
}
- template<class 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)
+ void priv_clear_pool()
{
- size_type remaining = n;
- while(remaining--){
- this->put_in_pool(this->allocate_one());
+ if(!this->index.empty() && this->index.back()){
+ node_base_ptr &pool_first_ref = *(this->index.end() - 2);
+ node_base_ptr &pool_last_ref = this->index.back();
+
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ this->deallocate_individual(holder);
+ pool_first_ref = pool_last_ref = 0;
+ this->internal_data.pool_size = 0;
}
}
- template<class 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)
+ void priv_increase_pool(size_type n)
{
- node_ptr &pool_first_ref = *(this->impl.end() - 2);
- node_ptr &pool_last_ref = this->impl.back();
+ node_base_ptr &pool_first_ref = *(this->index.end() - 2);
+ node_base_ptr &pool_last_ref = this->index.back();
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 (this->priv_node_alloc().allocate_individual(n));
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ multiallocation_chain m (this->allocate_individual(n));
holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
this->internal_data.pool_size += n;
std::pair<node_ptr, node_ptr> data(holder.extract_data());
@@ -1449,244 +1670,123 @@
pool_last_ref = data.second;
}
- void put_in_pool(node_ptr p)
+ void priv_put_in_pool(const node_ptr &p)
{
- node_ptr &pool_first_ref = *(this->impl.end()-2);
- node_ptr &pool_last_ref = this->impl.back();
+ node_base_ptr &pool_first_ref = *(this->index.end()-2);
+ node_base_ptr &pool_last_ref = this->index.back();
multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
holder.push_front(p);
++this->internal_data.pool_size;
std::pair<node_ptr, node_ptr> ret(holder.extract_data());
pool_first_ref = ret.first;
- pool_last_ref = ret.second;
+ pool_last_ref = ret.second;
}
node_ptr priv_get_from_pool()
{
- if(!this->impl.back()){
- return node_ptr(0);
- }
- else{
- node_ptr &pool_first_ref = *(this->impl.end() - 2);
- node_ptr &pool_last_ref = this->impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- node_ptr ret = holder.front();
- holder.pop_front();
- --this->internal_data.pool_size;
- if(!internal_data.pool_size){
- pool_first_ref = pool_last_ref = node_ptr();
- }
- else{
- std::pair<node_ptr, node_ptr> data(holder.extract_data());
- pool_first_ref = data.first;
- pool_last_ref = data.second;
- }
- return ret;
- }
- }
-
- void insert_iter_prolog(size_type n, difference_type d)
- {
- initialize_end_node(n);
- const void* old_ptr = &impl[0];
- //size_type old_capacity = this->capacity();
- //size_type old_size = this->size();
- this->impl.insert(this->impl.begin()+d, n, 0);
- bool realloced = &impl[0] != old_ptr;
- //Fix the pointers for the newly allocated buffer
- if(realloced){
- align_nodes(this->impl.begin(), this->impl.begin()+d);
- }
- }
-
- impl_iterator get_end_align()
- {
- return this->impl.end() - (ExtraPointers - 1);
- }
-
- static node_ptr_ptr ptr_to_node_ptr(node_ptr &n)
- { return node_ptr_ptr_traits::pointer_to(n); }
-
- void initialize_end_node(const size_type impl_capacity = 0)
- {
- if(this->impl.empty()){
- this->impl.reserve(impl_capacity + ExtraPointers);
- this->impl.resize(ExtraPointers);
- node_ptr &end_node_ref = impl[0];
- end_node_ref = this->get_end_node();
- this->internal_data.end_node.up = stable_vector::ptr_to_node_ptr(end_node_ref);
- }
- }
-
- void readjust_end_node()
- {
- if(!this->impl.empty()){
- node_ptr &end_node_ref = *(this->get_end_align()-1);
- end_node_ref = this->get_end_node();
- this->internal_data.end_node.up = node_ptr_ptr_traits::pointer_to(end_node_ref);
+ //Precondition: index is not empty
+ BOOST_ASSERT(!this->index.empty());
+ node_base_ptr &pool_first_ref = *(this->index.end() - 2);
+ node_base_ptr &pool_last_ref = this->index.back();
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ node_ptr ret = holder.front();
+ holder.pop_front();
+ --this->internal_data.pool_size;
+ if(!internal_data.pool_size){
+ pool_first_ref = pool_last_ref = node_ptr();
}
else{
- this->internal_data.end_node.up = node_ptr_ptr();
+ std::pair<node_ptr, node_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
}
+ return ret;
}
- node_ptr get_end_node() const
+ node_ptr priv_get_end_node() const
{
- return node_ptr_traits::static_cast_from
- (node_base_ptr_traits::pointer_to(const_cast<node_base_type&>(this->internal_data.end_node)));
+ return node_ptr_traits::pointer_to
+ (static_cast<node_type&>(const_cast<node_base_type&>(this->internal_data.end_node)));
}
- template<class Iter>
- node_ptr new_node(const node_ptr_ptr &up, Iter it)
- {
- node_ptr p = this->allocate_one();
- try{
- boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), it);
- //This does not throw
- ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
- p->up = up;
- }
- catch(...){
- this->deallocate_one(p);
- throw;
- }
- return p;
- }
-
- void delete_node(const node_ptr &n)
+ void priv_delete_node(const node_ptr &n)
{
allocator_traits<node_allocator_type>::
- destroy(this->priv_node_alloc(), container_detail::to_raw_pointer(n));
+ destroy(this->priv_node_alloc(), container_detail::addressof(n->value));
static_cast<node_base_type*>(container_detail::to_raw_pointer(n))->~node_base_type();
- this->put_in_pool(n);
- }
-
- static void align_nodes(impl_iterator first, impl_iterator last)
- {
- while(first!=last){
- (*first)->up = stable_vector::ptr_to_node_ptr(*first);
- ++first;
- }
+ this->priv_put_in_pool(n);
}
- template <class FwdIterator>
- void priv_insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
+ template<class Iterator>
+ void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
{
- size_type i=0;
- try{
- while(first!=last){
- it[i] = this->new_node(stable_vector::ptr_to_node_ptr(it[i]), first);
- ++first;
- ++i;
- }
- }
- catch(...){
- impl_iterator e = this->impl.erase(it + i, it + n);
- this->align_nodes(e, this->get_end_align());
- throw;
- }
- }
-
- template <class FwdIterator>
- void priv_insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
- {
- multiallocation_chain mem(this->priv_node_alloc().allocate_individual(n));
-
- size_type i = 0;
- node_ptr p = 0;
- try{
- while(first != last){
- p = mem.front();
- mem.pop_front();
- //This can throw
- boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first);
- //This does not throw
- ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
- p->up = stable_vector::ptr_to_node_ptr(it[i]);
- ++first;
- it[i] = p;
- ++i;
- }
- }
- catch(...){
- this->priv_node_alloc().deallocate_one(p);
- this->priv_node_alloc().deallocate_many(boost::move(mem));
- impl_iterator e = this->impl.erase(it+i, it+n);
- this->align_nodes(e, this->get_end_align());
- throw;
- }
- }
-
- template <class FwdIterator>
- void priv_insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
- {
- size_type i = 0;
- node_ptr p = 0;
- try{
- while(first != last){
- p = this->priv_get_from_pool();
- if(!p){
- this->priv_insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
- break;
- }
- //This can throw
- boost::container::construct_in_place(this->priv_node_alloc(), container_detail::addressof(p->value), first);
- //This does not throw
- ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
- p->up = stable_vector::ptr_to_node_ptr(it[i]);
- ++first;
- it[i]=p;
- ++i;
- }
- }
- catch(...){
- put_in_pool(p);
- impl_iterator e = this->impl.erase(it+i, it+n);
- this->align_nodes(e, this->get_end_align());
- throw;
- }
+ //This can throw
+ boost::container::construct_in_place
+ ( this->priv_node_alloc()
+ , container_detail::addressof(p->value)
+ , it);
+ //This does not throw
+ ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)))
+ node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
+ }
+
+ template<class ValueConvertible>
+ void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
+ {
+ //This can throw
+ boost::container::allocator_traits<node_allocator_type>::construct
+ ( this->priv_node_alloc()
+ , container_detail::addressof(p->value)
+ , ::boost::forward<ValueConvertible>(value_convertible));
+ //This does not throw
+ ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p))) node_base_type;
}
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();
+ index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
+ index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
}
#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
bool priv_invariant()const
{
- impl_type & impl_ref = const_cast<impl_type&>(this->impl);
+ index_type & index_ref = const_cast<index_type&>(this->index);
- if(impl_ref.empty())
+ if(index.empty())
return !this->capacity() && !this->size();
- if(this->get_end_node() != *(impl_ref.end() - ExtraPointers)){
+ if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
return false;
}
- for( impl_iterator it = impl_ref.begin()
- , it_end = const_cast<stable_vector&>(*this).get_end_align()
- ; it != it_end
- ; ++it){
- if((*it)->up != stable_vector::ptr_to_node_ptr(*it)){
- return false;
- }
+
+ if(!index_traits_type::invariants(index_ref)){
+ return false;
}
size_type n = this->capacity() - this->size();
- node_ptr &pool_first_ref = *(impl_ref.end() - 2);
- node_ptr &pool_last_ref = impl_ref.back();
+ node_base_ptr &pool_first_ref = *(index_ref.end() - 2);
+ node_base_ptr &pool_last_ref = index_ref.back();
multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
size_type num_pool = 0;
while(beg != end){
++num_pool;
++beg;
}
- return n >= num_pool;
+ return n >= num_pool && num_pool == internal_data.pool_size;
}
class invariant_checker
@@ -1729,7 +1829,7 @@
node_allocator_type &priv_node_alloc() { return internal_data; }
const node_allocator_type &priv_node_alloc() const { return internal_data; }
- impl_type impl;
+ index_type index;
/// @endcond
};
@@ -1788,24 +1888,3 @@
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_STABLE_VECTOR_HPP
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Modified: trunk/boost/container/vector.hpp
==============================================================================
--- trunk/boost/container/vector.hpp (original)
+++ trunk/boost/container/vector.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -1521,7 +1521,7 @@
container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
{
if(this->members_.m_capacity){
- if(!size()){
+ if(!this->size()){
this->prot_deallocate();
}
else{
Modified: trunk/libs/container/test/vector_test.hpp
==============================================================================
--- trunk/libs/container/test/vector_test.hpp (original)
+++ trunk/libs/container/test/vector_test.hpp 2012-09-09 17:47:32 EDT (Sun, 09 Sep 2012)
@@ -152,43 +152,47 @@
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
{
+ boostvector->resize(100);
+ stdvector->resize(100);
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
- IntType new_int(-1);
+ IntType new_int(-2);
aux_vect[i] = boost::move(new_int);
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
- aux_vect2[i] = -1;
+ aux_vect2[i] = -2;
}
+ typename MyBoostVector::size_type old_size = boostvector->size();
typename MyBoostVector::iterator insert_it =
- boostvector->insert(boostvector->begin()
+ boostvector->insert(boostvector->begin() + old_size
,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(boostvector->begin() + old_size != insert_it) return 1;
+ stdvector->insert(stdvector->begin() + old_size, aux_vect2, aux_vect2 + 50);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
for(int i = 0; i < 50; ++i){
- IntType new_int(-1);
+ IntType new_int(-3);
aux_vect[i] = boost::move(new_int);
}
for(int i = 0; i < 50; ++i){
- aux_vect2[i] = -1;
+ aux_vect2[i] = -3;
}
+ old_size = boostvector->size();
//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)
+ insert_it = boostvector->insert(boostvector->begin() + old_size
+ ,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(boostvector->begin() != insert_it) return 1;
- stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50);
+ if(boostvector->begin() + old_size != insert_it) return 1;
+ stdvector->insert(stdvector->begin() + old_size, aux_vect2, aux_vect2 + 50);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
-/*
+/* //deque has no reserve
boostvector->reserve(boostvector->size()*2);
stdvector->reserve(stdvector->size()*2);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
@@ -201,13 +205,27 @@
MyStdVector(*stdvector).swap(*stdvector);
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ { //push_back with not enough capacity
IntType push_back_this(1);
boostvector->push_back(boost::move(push_back_this));
stdvector->push_back(int(1));
boostvector->push_back(IntType(1));
stdvector->push_back(int(1));
+ if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
+ { //push_back with enough capacity
+ boostvector->pop_back();
+ boostvector->pop_back();
+ stdvector->pop_back();
+ stdvector->pop_back();
+ IntType push_back_this(1);
+ boostvector->push_back(boost::move(push_back_this));
+ stdvector->push_back(int(1));
+ boostvector->push_back(IntType(1));
+ stdvector->push_back(int(1));
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+ }
if(!vector_copyable_only(boostvector, stdvector
,container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
@@ -245,7 +263,7 @@
stdvector->assign(l.begin(), l.end());
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
}
-/*
+/* deque has no reserve or capacity
std::size_t cap = boostvector->capacity();
boostvector->reserve(cap*2);
stdvector->reserve(cap*2);
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk