mirror of
https://github.com/boostorg/container.git
synced 2025-08-03 06:24:26 +02:00
Reduced template code bloat making stable_vector's index independent from value_type.
[SVN r80478]
This commit is contained in:
@@ -27,6 +27,68 @@ namespace boost {
|
|||||||
namespace container {
|
namespace container {
|
||||||
namespace container_detail {
|
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
|
//!A deleter for scoped_ptr that deallocates the memory
|
||||||
//!allocated for an array of objects using a STL allocator.
|
//!allocated for an array of objects using a STL allocator.
|
||||||
template <class Allocator>
|
template <class Allocator>
|
||||||
@@ -239,10 +301,57 @@ class allocator_destroyer
|
|||||||
void operator()(const pointer &p)
|
void operator()(const pointer &p)
|
||||||
{
|
{
|
||||||
AllocTraits::destroy(a_, container_detail::to_raw_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_detail {
|
||||||
} //namespace container {
|
} //namespace container {
|
||||||
|
@@ -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)
|
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); }
|
{ 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); }
|
{ holder_.incorporate_after(after_this.base(), begin, before_end, n); }
|
||||||
|
|
||||||
void pop_front()
|
void pop_front()
|
||||||
|
@@ -43,99 +43,6 @@ namespace boost {
|
|||||||
namespace container {
|
namespace container {
|
||||||
namespace container_detail {
|
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>
|
template<class ValueCompare, class Node>
|
||||||
struct node_compare
|
struct node_compare
|
||||||
: private ValueCompare
|
: private ValueCompare
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1521,7 +1521,7 @@ class vector : private container_detail::vector_alloc_holder<A>
|
|||||||
container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
|
container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
|
||||||
{
|
{
|
||||||
if(this->members_.m_capacity){
|
if(this->members_.m_capacity){
|
||||||
if(!size()){
|
if(!this->size()){
|
||||||
this->prot_deallocate();
|
this->prot_deallocate();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@@ -152,43 +152,47 @@ int vector_test()
|
|||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
boostvector->resize(100);
|
||||||
|
stdvector->resize(100);
|
||||||
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
|
|
||||||
IntType aux_vect[50];
|
IntType aux_vect[50];
|
||||||
for(int i = 0; i < 50; ++i){
|
for(int i = 0; i < 50; ++i){
|
||||||
IntType new_int(-1);
|
IntType new_int(-2);
|
||||||
aux_vect[i] = boost::move(new_int);
|
aux_vect[i] = boost::move(new_int);
|
||||||
}
|
}
|
||||||
int aux_vect2[50];
|
int aux_vect2[50];
|
||||||
for(int i = 0; i < 50; ++i){
|
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 =
|
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[0])
|
||||||
,boost::make_move_iterator(aux_vect + 50));
|
,boost::make_move_iterator(aux_vect + 50));
|
||||||
if(boostvector->begin() != insert_it) return 1;
|
if(boostvector->begin() + old_size != insert_it) return 1;
|
||||||
stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50);
|
stdvector->insert(stdvector->begin() + old_size, aux_vect2, aux_vect2 + 50);
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
|
|
||||||
for(int i = 0; i < 50; ++i){
|
for(int i = 0; i < 50; ++i){
|
||||||
IntType new_int(-1);
|
IntType new_int(-3);
|
||||||
aux_vect[i] = boost::move(new_int);
|
aux_vect[i] = boost::move(new_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 50; ++i){
|
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
|
//Now try with input iterators instead
|
||||||
insert_it = boostvector->insert(boostvector->begin()
|
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[0]))
|
||||||
// ,boost::make_move_iterator(make_input_from_forward_iterator(aux_vect + 50))
|
,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;
|
if(boostvector->begin() + old_size != insert_it) return 1;
|
||||||
stdvector->insert(stdvector->begin(), aux_vect2, aux_vect2 + 50);
|
stdvector->insert(stdvector->begin() + old_size, aux_vect2, aux_vect2 + 50);
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
}
|
}
|
||||||
/*
|
/* //deque has no reserve
|
||||||
boostvector->reserve(boostvector->size()*2);
|
boostvector->reserve(boostvector->size()*2);
|
||||||
stdvector->reserve(stdvector->size()*2);
|
stdvector->reserve(stdvector->size()*2);
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
@@ -201,13 +205,27 @@ int vector_test()
|
|||||||
MyStdVector(*stdvector).swap(*stdvector);
|
MyStdVector(*stdvector).swap(*stdvector);
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
|
|
||||||
|
{ //push_back with not enough capacity
|
||||||
IntType push_back_this(1);
|
IntType push_back_this(1);
|
||||||
boostvector->push_back(boost::move(push_back_this));
|
boostvector->push_back(boost::move(push_back_this));
|
||||||
stdvector->push_back(int(1));
|
stdvector->push_back(int(1));
|
||||||
boostvector->push_back(IntType(1));
|
boostvector->push_back(IntType(1));
|
||||||
stdvector->push_back(int(1));
|
stdvector->push_back(int(1));
|
||||||
|
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 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
|
if(!vector_copyable_only(boostvector, stdvector
|
||||||
,container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
|
,container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
|
||||||
@@ -245,7 +263,7 @@ int vector_test()
|
|||||||
stdvector->assign(l.begin(), l.end());
|
stdvector->assign(l.begin(), l.end());
|
||||||
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
|
||||||
}
|
}
|
||||||
/*
|
/* deque has no reserve or capacity
|
||||||
std::size_t cap = boostvector->capacity();
|
std::size_t cap = boostvector->capacity();
|
||||||
boostvector->reserve(cap*2);
|
boostvector->reserve(cap*2);
|
||||||
stdvector->reserve(cap*2);
|
stdvector->reserve(cap*2);
|
||||||
|
Reference in New Issue
Block a user