forked from boostorg/container
Fixes #145 ("Allocations not handled correctly in some cases of vector move with unequal allocators")
This commit is contained in:
@@ -78,6 +78,7 @@ template< class T
|
||||
, bool PropagateOnContMoveAssign
|
||||
, bool PropagateOnContSwap
|
||||
, bool CopyOnPropagateOnContSwap
|
||||
, bool EqualIfEqualIds
|
||||
>
|
||||
class propagation_test_allocator
|
||||
{
|
||||
@@ -99,7 +100,8 @@ class propagation_test_allocator
|
||||
, PropagateOnContCopyAssign
|
||||
, PropagateOnContMoveAssign
|
||||
, PropagateOnContSwap
|
||||
, CopyOnPropagateOnContSwap> other;
|
||||
, CopyOnPropagateOnContSwap
|
||||
, EqualIfEqualIds> other;
|
||||
};
|
||||
|
||||
propagation_test_allocator select_on_container_copy_construction() const
|
||||
@@ -129,7 +131,8 @@ class propagation_test_allocator
|
||||
, PropagateOnContCopyAssign
|
||||
, PropagateOnContMoveAssign
|
||||
, PropagateOnContSwap
|
||||
, CopyOnPropagateOnContSwap> &x)
|
||||
, CopyOnPropagateOnContSwap
|
||||
, EqualIfEqualIds> &x)
|
||||
: id_(x.id_)
|
||||
, ctr_copies_(x.ctr_copies_+1)
|
||||
, ctr_moves_(0)
|
||||
@@ -178,11 +181,11 @@ class propagation_test_allocator
|
||||
void deallocate(T*p, std::size_t)
|
||||
{ delete[] ((char*)p);}
|
||||
|
||||
friend bool operator==(const propagation_test_allocator &, const propagation_test_allocator &)
|
||||
{ return true; }
|
||||
friend bool operator==(const propagation_test_allocator &a, const propagation_test_allocator &b)
|
||||
{ return EqualIfEqualIds ? a.id_ == b.id_ : true; }
|
||||
|
||||
friend bool operator!=(const propagation_test_allocator &, const propagation_test_allocator &)
|
||||
{ return false; }
|
||||
friend bool operator!=(const propagation_test_allocator &a, const propagation_test_allocator &b)
|
||||
{ return EqualIfEqualIds ? a.id_ != b.id_ : false; }
|
||||
|
||||
void swap(propagation_test_allocator &r)
|
||||
{
|
||||
@@ -214,12 +217,15 @@ template< class T
|
||||
, bool PropagateOnContMoveAssign
|
||||
, bool PropagateOnContSwap
|
||||
, bool CopyOnPropagateOnContSwap
|
||||
, bool EqualIfEqualIds
|
||||
>
|
||||
unsigned int propagation_test_allocator< T
|
||||
, PropagateOnContCopyAssign
|
||||
, PropagateOnContMoveAssign
|
||||
, PropagateOnContSwap
|
||||
, CopyOnPropagateOnContSwap>::unique_id_ = 0;
|
||||
, CopyOnPropagateOnContSwap
|
||||
, EqualIfEqualIds
|
||||
>::unique_id_ = 0;
|
||||
|
||||
|
||||
} //namespace test {
|
||||
|
||||
@@ -110,7 +110,7 @@ template<class Selector>
|
||||
bool test_propagate_allocator()
|
||||
{
|
||||
{
|
||||
typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate;
|
||||
typedef propagation_test_allocator<char, true, true, true, true, true> AlwaysPropagate;
|
||||
typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector> PropagateCont;
|
||||
typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
|
||||
{
|
||||
@@ -213,7 +213,7 @@ bool test_propagate_allocator()
|
||||
//Test NeverPropagate allocator propagation
|
||||
//////////////////////////////////////////
|
||||
{
|
||||
typedef propagation_test_allocator<char, false, false, false, false> NeverPropagate;
|
||||
typedef propagation_test_allocator<char, false, false, false, false, true> NeverPropagate;
|
||||
typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
|
||||
typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
|
||||
{
|
||||
@@ -281,6 +281,15 @@ bool test_propagate_allocator()
|
||||
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
|
||||
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
|
||||
}
|
||||
//And now allocator argument constructors
|
||||
test_propagate_allocator_allocator_arg<NoPropagateCont>();
|
||||
}
|
||||
{
|
||||
//Don't use unequal ids as unequal allocators -------------------------|,
|
||||
//because swap requires equal allocators v
|
||||
typedef propagation_test_allocator<char, false, false, false, false, false> NeverPropagate;
|
||||
typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
|
||||
typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
|
||||
{
|
||||
//swap
|
||||
StoredAllocator::reset_unique_id(666);
|
||||
@@ -302,8 +311,6 @@ bool test_propagate_allocator()
|
||||
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
|
||||
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
|
||||
}
|
||||
//And now allocator argument constructors
|
||||
test_propagate_allocator_allocator_arg<NoPropagateCont>();
|
||||
}
|
||||
|
||||
return report_errors() == 0;
|
||||
|
||||
@@ -59,18 +59,18 @@ public:
|
||||
|
||||
template <typename T> friend class SimpleAllocator;
|
||||
|
||||
friend bool operator == (const SimpleAllocator &, const SimpleAllocator &)
|
||||
{ return true; }
|
||||
friend bool operator == (const SimpleAllocator &a, const SimpleAllocator &b)
|
||||
{ return a.m_state == b.m_state; }
|
||||
|
||||
friend bool operator != (const SimpleAllocator &, const SimpleAllocator &)
|
||||
{ return false; }
|
||||
friend bool operator != (const SimpleAllocator &a, const SimpleAllocator &b)
|
||||
{ return a.m_state != b.m_state; }
|
||||
};
|
||||
|
||||
class alloc_int
|
||||
{
|
||||
private: // Not copyable
|
||||
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int)
|
||||
BOOST_COPYABLE_AND_MOVABLE(alloc_int)
|
||||
|
||||
public:
|
||||
typedef SimpleAllocator<int> allocator_type;
|
||||
@@ -87,13 +87,30 @@ class alloc_int
|
||||
other.m_value = -1;
|
||||
}
|
||||
|
||||
alloc_int(const alloc_int &other)
|
||||
: m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
|
||||
{
|
||||
}
|
||||
|
||||
alloc_int(const alloc_int &other, const allocator_type &allocator)
|
||||
: m_value(other.m_value), m_allocator(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
alloc_int(int value, const allocator_type &allocator)
|
||||
: m_value(value), m_allocator(allocator)
|
||||
{}
|
||||
|
||||
alloc_int & operator=(BOOST_RV_REF(alloc_int)other)
|
||||
{
|
||||
other.m_value = other.m_value;
|
||||
m_value = other.m_value;
|
||||
other.m_value = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
alloc_int & operator=(const alloc_int &other)
|
||||
{
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -368,24 +385,47 @@ bool one_level_allocator_propagation_test()
|
||||
{
|
||||
allocator_type al(SimpleAllocator<value_type>(4));
|
||||
ContainerWrapper c2(al);
|
||||
{
|
||||
iterator it = c2.emplace(c2.cbegin(), 41);
|
||||
if(!test_value_and_state_equals(*it, 41, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator<value_type>(5)));
|
||||
|
||||
c.clear();
|
||||
iterator it = c.emplace(c.cbegin(), 42);
|
||||
|
||||
if(!test_value_and_state_equals(*it, 42, 5))
|
||||
if(!test_value_and_state_equals(*c.begin(), 41, 5))
|
||||
return false;
|
||||
}/*
|
||||
|
||||
{
|
||||
c.clear();
|
||||
iterator it = c.emplace(c.cbegin(), 42);
|
||||
|
||||
if(!test_value_and_state_equals(*it, 42, 5))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
{
|
||||
ContainerWrapper c2(allocator_type(SimpleAllocator<value_type>(3)));
|
||||
allocator_type al(SimpleAllocator<value_type>(4));
|
||||
ContainerWrapper c2(al);
|
||||
{
|
||||
iterator it = c2.emplace(c2.cbegin(), 41);
|
||||
if(!test_value_and_state_equals(*it, 41, 4))
|
||||
return false;
|
||||
}
|
||||
|
||||
ContainerWrapper c(c2, allocator_type(SimpleAllocator<value_type>(5)));
|
||||
|
||||
c.clear();
|
||||
iterator it = c.emplace(c.cbegin(), 42);
|
||||
|
||||
if(!test_value_and_state_equals(*it, 42, 5))
|
||||
if(!test_value_and_state_equals(*c.begin(), 41, 5))
|
||||
return false;
|
||||
}*/
|
||||
|
||||
{
|
||||
c.clear();
|
||||
iterator it = c.emplace(c.cbegin(), 42);
|
||||
|
||||
if(!test_value_and_state_equals(*it, 42, 5))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user