Improve allocator propagation test with new constructors and refactor code to avoid too many wrappers.

This commit is contained in:
Ion Gaztañaga
2015-02-26 00:31:19 +01:00
parent 7160bea2aa
commit 6c5e527c60
14 changed files with 548 additions and 302 deletions

View File

@@ -141,6 +141,9 @@ class flat_map
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
private:
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -1149,6 +1152,9 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
private:
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -1978,4 +1984,4 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T
#include <boost/container/detail/config_end.hpp>
#endif /* BOOST_CONTAINER_FLAT_MAP_HPP */
#endif // BOOST_CONTAINER_FLAT_MAP_HPP

View File

@@ -1346,4 +1346,4 @@ namespace container {
#include <boost/container/detail/config_end.hpp>
#endif /* BOOST_CONTAINER_FLAT_SET_HPP */
#endif // BOOST_CONTAINER_FLAT_SET_HPP

View File

@@ -366,6 +366,22 @@ bool test_support_for_initialization_list()
}
struct boost_container_deque;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_deque>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::deque<T, Allocator> type;
};
};
}}} //namespace boost::container::test
int main ()
{
if(!do_test<int>())
@@ -434,7 +450,7 @@ int main ()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<deque>())
if(!boost::container::test::test_propagate_allocator<boost_container_deque>())
return 1;
return 0;

View File

@@ -238,7 +238,7 @@ class propagation_test_allocator
{ return CopyOnPropagateOnContSwap ? propagation_test_allocator(*this) : propagation_test_allocator(); }
explicit propagation_test_allocator()
: id_(unique_id_++)
: id_(++unique_id_)
, ctr_copies_(0)
, ctr_moves_(0)
, assign_copies_(0)
@@ -263,7 +263,7 @@ class propagation_test_allocator
, PropagateOnContSwap
, CopyOnPropagateOnContSwap> &x)
: id_(x.id_)
, ctr_copies_(0)
, ctr_copies_(x.ctr_copies_+1)
, ctr_moves_(0)
, assign_copies_(0)
, assign_moves_(0)
@@ -301,8 +301,8 @@ class propagation_test_allocator
return *this;
}
static void reset_unique_id()
{ unique_id_ = 0; }
static void reset_unique_id(unsigned id = 0)
{ unique_id_ = id; }
T* allocate(std::size_t n)
{ return (T*)::new char[sizeof(T)*n]; }

View File

@@ -199,40 +199,6 @@ void test_move()
move_assign.swap(original);
}
template<class T, class Allocator>
class flat_map_propagate_test_wrapper
: public boost::container::flat_map
< T, T, std::less<T>
, typename boost::container::allocator_traits<Allocator>::template
portable_rebind_alloc< std::pair<T, T> >::type>
{
BOOST_COPYABLE_AND_MOVABLE(flat_map_propagate_test_wrapper)
typedef boost::container::flat_map
< T, T, std::less<T>
, typename boost::container::allocator_traits<Allocator>::template
portable_rebind_alloc< std::pair<T, T> >::type> Base;
public:
flat_map_propagate_test_wrapper()
: Base()
{}
flat_map_propagate_test_wrapper(const flat_map_propagate_test_wrapper &x)
: Base(x)
{}
flat_map_propagate_test_wrapper(BOOST_RV_REF(flat_map_propagate_test_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
flat_map_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(flat_map_propagate_test_wrapper) x)
{ this->Base::operator=(x); return *this; }
flat_map_propagate_test_wrapper &operator=(BOOST_RV_REF(flat_map_propagate_test_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(flat_map_propagate_test_wrapper &x)
{ this->Base::swap(x); }
};
namespace boost{
namespace container {
@@ -347,6 +313,49 @@ struct GetAllocatorMap
};
};
struct boost_container_flat_map;
struct boost_container_flat_multimap;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_flat_map>
{
template <class T, class Allocator>
struct apply
{
typedef typename boost::container::allocator_traits<Allocator>::
template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
typedef boost::container::flat_map<T, T, std::less<T>, TypeAllocator> type;
};
};
template<>
struct alloc_propagate_base<boost_container_flat_multimap>
{
template <class T, class Allocator>
struct apply
{
typedef typename boost::container::allocator_traits<Allocator>::
template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
typedef boost::container::flat_multimap<T, T, std::less<T>, TypeAllocator> type;
};
};
template <class Key, class T, class Compare, class Allocator>
struct get_real_stored_allocator<flat_map<Key, T, Compare, Allocator> >
{
typedef typename flat_map<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
};
template <class Key, class T, class Compare, class Allocator>
struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
{
typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
};
}}} //namespace boost::container::test
template<class VoidAllocator>
int test_map_variants()
{
@@ -516,7 +525,10 @@ int main()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<flat_map_propagate_test_wrapper>())
if(!boost::container::test::test_propagate_allocator<boost_container_flat_map>())
return 1;
if(!boost::container::test::test_propagate_allocator<boost_container_flat_multimap>())
return 1;
return 0;

View File

@@ -227,35 +227,6 @@ void test_move()
move_assign.swap(original);
}
template<class T, class Allocator>
class flat_set_propagate_test_wrapper
: public boost::container::flat_set<T, std::less<T>, Allocator>
{
BOOST_COPYABLE_AND_MOVABLE(flat_set_propagate_test_wrapper)
typedef boost::container::flat_set<T, std::less<T>, Allocator> Base;
public:
flat_set_propagate_test_wrapper()
: Base()
{}
flat_set_propagate_test_wrapper(const flat_set_propagate_test_wrapper &x)
: Base(x)
{}
flat_set_propagate_test_wrapper(BOOST_RV_REF(flat_set_propagate_test_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
flat_set_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(flat_set_propagate_test_wrapper) x)
{ this->Base::operator=(x); return *this; }
flat_set_propagate_test_wrapper &operator=(BOOST_RV_REF(flat_set_propagate_test_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(flat_set_propagate_test_wrapper &x)
{ this->Base::swap(x); }
};
namespace boost{
namespace container {
namespace test{
@@ -518,6 +489,35 @@ bool test_support_for_initialization_list_for()
return true;
}
struct boost_container_flat_set;
struct boost_container_flat_multiset;
namespace boost {
namespace container {
namespace test {
template<>
struct alloc_propagate_base<boost_container_flat_set>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::flat_set<T, std::less<T>, Allocator> type;
};
};
template<>
struct alloc_propagate_base<boost_container_flat_multiset>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::flat_multiset<T, std::less<T>, Allocator> type;
};
};
}}} //boost::container::test
int main()
{
using namespace boost::container::test;
@@ -599,7 +599,10 @@ int main()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<flat_set_propagate_test_wrapper>())
if(!boost::container::test::test_propagate_allocator<boost_container_flat_set>())
return 1;
if(!boost::container::test::test_propagate_allocator<boost_container_flat_multiset>())
return 1;
return 0;

View File

@@ -150,6 +150,22 @@ bool test_support_for_initializer_list()
return true;
}
struct boost_container_list;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_list>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::list<T, Allocator> type;
};
};
}}} //namespace boost::container::test
int main ()
{
recursive_list_test();
@@ -197,7 +213,7 @@ int main ()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<list>())
if(!boost::container::test::test_propagate_allocator<boost_container_list>())
return 1;
if(!test_support_for_initializer_list())

View File

@@ -235,45 +235,6 @@ void test_move()
move_assign.swap(original);
}
template<class T, class Allocator>
class map_propagate_test_wrapper
: public boost::container::map
< T, T, std::less<T>
, typename boost::container::allocator_traits<Allocator>::template
portable_rebind_alloc< std::pair<const T, T> >::type
//tree_assoc_defaults
>
{
BOOST_COPYABLE_AND_MOVABLE(map_propagate_test_wrapper)
typedef boost::container::map
< T, T, std::less<T>
, typename boost::container::allocator_traits<Allocator>::template
portable_rebind_alloc< std::pair<const T, T> >::type
> Base;
public:
map_propagate_test_wrapper()
: Base()
{}
map_propagate_test_wrapper(const map_propagate_test_wrapper &x)
: Base(x)
{}
map_propagate_test_wrapper(BOOST_RV_REF(map_propagate_test_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
map_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(map_propagate_test_wrapper) x)
{ this->Base::operator=(x); return *this; }
map_propagate_test_wrapper &operator=(BOOST_RV_REF(map_propagate_test_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(map_propagate_test_wrapper &x)
{ this->Base::swap(x); }
};
template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorMap
{
@@ -389,6 +350,37 @@ bool test_support_for_initialization_list_for()
return true;
}
struct boost_container_map;
struct boost_container_multimap;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_map>
{
template <class T, class Allocator>
struct apply
{
typedef typename boost::container::allocator_traits<Allocator>::
template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
typedef boost::container::map<T, T, std::less<T>, TypeAllocator> type;
};
};
template<>
struct alloc_propagate_base<boost_container_multimap>
{
template <class T, class Allocator>
struct apply
{
typedef typename boost::container::allocator_traits<Allocator>::
template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
typedef boost::container::multimap<T, T, std::less<T>, TypeAllocator> type;
};
};
}}} //namespace boost::container::test
int main ()
{
//Recursive container instantiation
@@ -462,7 +454,10 @@ int main ()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<map_propagate_test_wrapper>())
if(!boost::container::test::test_propagate_allocator<boost_container_map>())
return 1;
if(!boost::container::test::test_propagate_allocator<boost_container_multimap>())
return 1;
if(!test_support_for_initialization_list_for<map<int, int> >())

View File

@@ -20,81 +20,165 @@ namespace boost{
namespace container {
namespace test{
template<template<class, class> class ContainerWrapper>
template<class Selector>
struct alloc_propagate_base;
template<class T, class Allocator, class Selector>
class alloc_propagate_wrapper
: public alloc_propagate_base<Selector>::template apply<T, Allocator>::type
{
BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper)
public:
typedef typename alloc_propagate_base
<Selector>::template apply<T, Allocator>::type Base;
typedef typename Base::allocator_type allocator_type;
alloc_propagate_wrapper()
: Base()
{}
explicit alloc_propagate_wrapper(const allocator_type &a)
: Base(a)
{}
alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
: Base(x)
{}
alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
: Base(x, a)
{}
alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a)
: Base(boost::move(static_cast<Base&>(x)), a)
{}
alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
{ this->Base::operator=(x); return *this; }
alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(alloc_propagate_wrapper &x)
{ this->Base::swap(x); }
};
template<class T>
struct get_real_stored_allocator
{
typedef typename T::stored_allocator_type type;
};
template<class Container>
void test_propagate_allocator_allocator_arg();
template<class Selector>
bool test_propagate_allocator()
{
{
typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate;
typedef ContainerWrapper<char, AlwaysPropagate> PropagateCont;
//////////////////////////////////////////
//Test AlwaysPropagate allocator propagation
//////////////////////////////////////////
AlwaysPropagate::reset_unique_id();
//default constructor
PropagateCont c;
BOOST_TEST (c.get_stored_allocator().id_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
//copy constructor
PropagateCont c2(c);
//propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
//For allocators that copy in select_on_container_copy_construction, at least we must have a copy
unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_;
unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_;
BOOST_TEST (c2.get_stored_allocator().id_ == 0);
BOOST_TEST (ctr_copies > 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
//move constructor
PropagateCont c3(boost::move(c2));
BOOST_TEST (c3.get_stored_allocator().id_ == 0);
BOOST_TEST (c3.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c3.get_stored_allocator().ctr_moves_ > ctr_moves);
ctr_moves = c3.get_stored_allocator().ctr_moves_;
BOOST_TEST (ctr_moves > 0);
BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c3.get_stored_allocator().swaps_ == 0);
//copy assign
c2 = c3;
unsigned int assign_copies = c2.get_stored_allocator().assign_copies_;
BOOST_TEST (c2.get_stored_allocator().id_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == ctr_moves);
BOOST_TEST (assign_copies == 1);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
//move assign
c = boost::move(c2);
unsigned int assign_moves = c.get_stored_allocator().assign_moves_;
BOOST_TEST (c.get_stored_allocator().id_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == ctr_moves);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == assign_copies);
BOOST_TEST (assign_moves == 1);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
//swap
c.get_stored_allocator().id_ = 999;
c.swap(c2);
unsigned int swaps = c2.get_stored_allocator().swaps_;
BOOST_TEST (c2.get_stored_allocator().id_ == 999);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == ctr_moves);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == assign_copies);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == assign_moves);
BOOST_TEST (swaps == 1);
typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector> PropagateCont;
typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
{
//////////////////////////////////////////
//Test AlwaysPropagate allocator propagation
//////////////////////////////////////////
//default constructor
StoredAllocator::reset_unique_id(111);
PropagateCont c; //stored 112
BOOST_TEST (c.get_stored_allocator().id_ == 112);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
}
{
//copy constructor
StoredAllocator::reset_unique_id(222);
PropagateCont c; //stored 223
BOOST_TEST (c.get_stored_allocator().id_ == 223);
//propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
//For allocators that copy in select_on_container_copy_construction, at least we must have a copy
PropagateCont c2(c); //should propagate 223
BOOST_TEST (c2.get_stored_allocator().id_ == 223);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//move constructor
StoredAllocator::reset_unique_id(333);
PropagateCont c; //stored 334
BOOST_TEST (c.get_stored_allocator().id_ == 334);
PropagateCont c2(boost::move(c)); //should propagate 334
BOOST_TEST (c2.get_stored_allocator().id_ == 334);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//copy assign
StoredAllocator::reset_unique_id(444);
PropagateCont c; //stored 445
BOOST_TEST (c.get_stored_allocator().id_ == 445);
PropagateCont c2; //stored 446
BOOST_TEST (c2.get_stored_allocator().id_ == 446);
c2 = c; //should propagate 445
BOOST_TEST (c2.get_stored_allocator().id_ == 445);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//move assign
StoredAllocator::reset_unique_id(555);
PropagateCont c; //stored 556
BOOST_TEST (c.get_stored_allocator().id_ == 556);
PropagateCont c2; //stored 557
BOOST_TEST (c2.get_stored_allocator().id_ == 557);
c = boost::move(c2); //should propagate 557
BOOST_TEST (c.get_stored_allocator().id_ == 557);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 1);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
}
{
//swap
StoredAllocator::reset_unique_id(666);
PropagateCont c; //stored 667
BOOST_TEST (c.get_stored_allocator().id_ == 667);
PropagateCont c2; //stored 668
BOOST_TEST (c2.get_stored_allocator().id_ == 668);
c.swap(c2);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 1);
BOOST_TEST (c.get_stored_allocator().swaps_ == 1);
}
//And now allocator argument constructors
test_propagate_allocator_allocator_arg<PropagateCont>();
}
//////////////////////////////////////////
@@ -102,74 +186,149 @@ bool test_propagate_allocator()
//////////////////////////////////////////
{
typedef propagation_test_allocator<char, false, false, false, false> NeverPropagate;
typedef ContainerWrapper<char, NeverPropagate> NoPropagateCont;
NeverPropagate::reset_unique_id();
typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
{
//default constructor
StoredAllocator::reset_unique_id(111);
NoPropagateCont c; //stored 112
BOOST_TEST (c.get_stored_allocator().id_ == 112);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
}
{
//copy constructor
//propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
//For allocators that don't copy in select_on_container_copy_construction we must have a default
//construction
StoredAllocator::reset_unique_id(222);
NoPropagateCont c; //stored 223
BOOST_TEST (c.get_stored_allocator().id_ == 223);
NoPropagateCont c2(c); //should NOT propagate 223
BOOST_TEST (c2.get_stored_allocator().id_ == 224);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//move constructor
StoredAllocator::reset_unique_id(333);
NoPropagateCont c; //stored 334
BOOST_TEST (c.get_stored_allocator().id_ == 334);
NoPropagateCont c2(boost::move(c)); // should NOT propagate 334
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//copy assign
StoredAllocator::reset_unique_id(444);
NoPropagateCont c; //stored 445
NoPropagateCont c2; //stored 446
c2 = c; // should NOT propagate 445
BOOST_TEST (c2.get_stored_allocator().id_ == 446);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//move assign
StoredAllocator::reset_unique_id(555);
NoPropagateCont c; //stored 556
NoPropagateCont c2; //stored 557
c2 = c; // should NOT propagate 556
BOOST_TEST (c2.get_stored_allocator().id_ == 557);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//swap
StoredAllocator::reset_unique_id(666);
NoPropagateCont c; //stored 667
BOOST_TEST (c.get_stored_allocator().id_ == 667);
NoPropagateCont c2; //stored 668
BOOST_TEST (c2.get_stored_allocator().id_ == 668);
c2.swap(c); // should NOT swap 667 and 668
BOOST_TEST (c2.get_stored_allocator().id_ == 668);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
BOOST_TEST (c.get_stored_allocator().id_ == 667);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
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>();
}
//default constructor
NoPropagateCont c;
BOOST_TEST (c.get_stored_allocator().id_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
return report_errors() == 0;
}
template<class Container>
void test_propagate_allocator_allocator_arg()
{
typedef typename Container::allocator_type allocator_type;
typedef typename get_real_stored_allocator<typename Container::Base>::type StoredAllocator;
{ //The allocator must be always propagated
//allocator constructor
allocator_type::reset_unique_id(111);
const allocator_type & a = allocator_type(); //stored 112
Container c(a); //should propagate 112
BOOST_TEST (c.get_stored_allocator().id_ == 112);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ > 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
//copy constructor
//propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
//For allocators that don't copy in select_on_container_copy_construction we must have a default
//construction
NoPropagateCont c2(c);
unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_;
unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_;
BOOST_TEST (c2.get_stored_allocator().id_ == 1);
BOOST_TEST (ctr_copies >= 0);
BOOST_TEST (ctr_moves >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
//move constructor
NoPropagateCont c3(boost::move(c2));
BOOST_TEST (c3.get_stored_allocator().id_ == 1);
BOOST_TEST (c3.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c3.get_stored_allocator().ctr_moves_ > ctr_moves);
unsigned int ctr_moves2 = ctr_moves;
ctr_moves = c3.get_stored_allocator().ctr_moves_;
BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c3.get_stored_allocator().swaps_ == 0);
//copy assign
c2 = c3;
BOOST_TEST (c2.get_stored_allocator().id_ == 1);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == ctr_moves2);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
//move assign
c = boost::move(c2);
BOOST_TEST (c.get_stored_allocator().id_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
//swap
c.get_stored_allocator().id_ = 999;
c2.swap(c);
BOOST_TEST (c2.get_stored_allocator().id_ == 1);
BOOST_TEST (c.get_stored_allocator().id_ == 999);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == ctr_moves2);
}
{
//copy allocator constructor
StoredAllocator::reset_unique_id(999);
Container c;
//stored_allocator_type could be the same type as allocator_type
//so reset it again to get a predictable result
allocator_type::reset_unique_id(222);
Container c2(c, allocator_type()); //should propagate 223
BOOST_TEST (c2.get_stored_allocator().id_ == 223);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
{
//move allocator constructor
StoredAllocator::reset_unique_id(999);
Container c;
//stored_allocator_type could be the same type as allocator_type
//so reset it again to get a predictable result
allocator_type::reset_unique_id(333);
Container c2(boost::move(c), allocator_type()); //should propagate 334
BOOST_TEST (c2.get_stored_allocator().id_ == 334);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
return report_errors() == 0;
}
} //namespace test{

View File

@@ -212,37 +212,35 @@ void test_move()
move_assign.swap(original);
}
template<class T, class Allocator>
class set_propagate_test_wrapper
: public boost::container::set<T, std::less<T>, Allocator
//tree_assoc_defaults
>
struct boost_container_set;
struct boost_container_multiset;
namespace boost {
namespace container {
namespace test {
template<>
struct alloc_propagate_base<boost_container_set>
{
BOOST_COPYABLE_AND_MOVABLE(set_propagate_test_wrapper)
typedef boost::container::set<T, std::less<T>, Allocator > Base;
public:
set_propagate_test_wrapper()
: Base()
{}
set_propagate_test_wrapper(const set_propagate_test_wrapper &x)
: Base(x)
{}
set_propagate_test_wrapper(BOOST_RV_REF(set_propagate_test_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
set_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(set_propagate_test_wrapper) x)
{ this->Base::operator=(x); return *this; }
set_propagate_test_wrapper &operator=(BOOST_RV_REF(set_propagate_test_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(set_propagate_test_wrapper &x)
{ this->Base::swap(x); }
template <class T, class Allocator>
struct apply
{
typedef boost::container::set<T, std::less<T>, Allocator> type;
};
};
template<>
struct alloc_propagate_base<boost_container_multiset>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::multiset<T, std::less<T>, Allocator> type;
};
};
}}} //boost::container::test
template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorSet
{
@@ -427,7 +425,10 @@ int main ()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<set_propagate_test_wrapper>())
if(!boost::container::test::test_propagate_allocator<boost_container_set>())
return 1;
if(!boost::container::test::test_propagate_allocator<boost_container_multiset>())
return 1;
if(!test_support_for_initialization_list_for<set<int> >())

View File

@@ -147,6 +147,24 @@ bool test_support_for_initializer_list()
return true;
}
struct boost_container_slist;
namespace boost {
namespace container {
namespace test {
template<>
struct alloc_propagate_base<boost_container_slist>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::slist<T, Allocator> type;
};
};
}}}
int main ()
{
recursive_slist_test();
@@ -202,7 +220,7 @@ int main ()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<slist>())
if(!boost::container::test::test_propagate_allocator<boost_container_slist>())
return 1;
if(!test_support_for_initializer_list())

View File

@@ -113,6 +113,23 @@ int test_cont_variants()
return 0;
}
struct boost_container_stable_vector;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_stable_vector>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::stable_vector<T, Allocator> type;
};
};
}}} //namespace boost::container::test
int main()
{
recursive_vector_test();
@@ -176,7 +193,7 @@ int main()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<stable_vector>())
if(!boost::container::test::test_propagate_allocator<boost_container_stable_vector>())
return 1;
////////////////////////////////////

View File

@@ -432,35 +432,22 @@ bool test_expand_bwd()
return test::test_all_expand_bwd<string_type>();
}
template<class T, class Allocator>
class string_propagate_test_wrapper
: public basic_string<T, std::char_traits<T>, Allocator>
struct boost_container_string;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_string>
{
BOOST_COPYABLE_AND_MOVABLE(string_propagate_test_wrapper)
typedef basic_string<T, std::char_traits<T>, Allocator> Base;
public:
string_propagate_test_wrapper()
: Base()
{}
string_propagate_test_wrapper(const string_propagate_test_wrapper &x)
: Base(x)
{}
string_propagate_test_wrapper(BOOST_RV_REF(string_propagate_test_wrapper) x)
: Base(boost::move(static_cast<Base&>(x)))
{}
string_propagate_test_wrapper &operator=(BOOST_COPY_ASSIGN_REF(string_propagate_test_wrapper) x)
{ this->Base::operator=(x); return *this; }
string_propagate_test_wrapper &operator=(BOOST_RV_REF(string_propagate_test_wrapper) x)
{ this->Base::operator=(boost::move(static_cast<Base&>(x))); return *this; }
void swap(string_propagate_test_wrapper &x)
{ this->Base::swap(x); }
template <class T, class Allocator>
struct apply
{
typedef boost::container::basic_string<T, std::char_traits<T>, Allocator> type;
};
};
}}} //namespace boost::container::test
int main()
{
if(string_test<char>()){
@@ -480,7 +467,7 @@ int main()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<string_propagate_test_wrapper>())
if(!boost::container::test::test_propagate_allocator<boost_container_string>())
return 1;
////////////////////////////////////

View File

@@ -145,6 +145,22 @@ int test_cont_variants()
return 0;
}
struct boost_container_vector;
namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_vector>
{
template <class T, class Allocator>
struct apply
{
typedef boost::container::vector<T, Allocator> type;
};
};
}}} //namespace boost::container::test
int main()
{
{
@@ -235,7 +251,7 @@ int main()
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<vector>()){
if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
return 1;
}