Reduced template code bloat making stable_vector's index independent from value_type.

[SVN r80478]
This commit is contained in:
Ion Gaztañaga
2012-09-09 21:47:32 +00:00
parent a8d20305dc
commit 22a18c25fb
6 changed files with 700 additions and 587 deletions

View File

@@ -27,6 +27,68 @@ namespace boost {
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 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>
@@ -239,10 +301,57 @@ class allocator_destroyer
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 {

View File

@@ -200,7 +200,7 @@ class transform_multiallocation_chain
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()

View File

@@ -43,99 +43,6 @@ namespace boost {
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

File diff suppressed because it is too large Load Diff

View File

@@ -1521,7 +1521,7 @@ class vector : private container_detail::vector_alloc_holder<A>
container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
{
if(this->members_.m_capacity){
if(!size()){
if(!this->size()){
this->prot_deallocate();
}
else{

View File

@@ -152,43 +152,47 @@ int vector_test()
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 @@ int vector_test()
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 @@ int vector_test()
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);