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; <typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; <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 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -1149,6 +1152,9 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl; <typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
typedef typename container_detail::get_flat_tree_iterators typedef typename container_detail::get_flat_tree_iterators
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; <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 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -1978,4 +1984,4 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T
#include <boost/container/detail/config_end.hpp> #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> #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 () int main ()
{ {
if(!do_test<int>()) if(!do_test<int>())
@@ -434,7 +450,7 @@ int main ()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // Allocator propagation testing
//////////////////////////////////// ////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<deque>()) if(!boost::container::test::test_propagate_allocator<boost_container_deque>())
return 1; return 1;
return 0; return 0;

View File

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

View File

@@ -199,40 +199,6 @@ void test_move()
move_assign.swap(original); 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 boost{
namespace container { 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> template<class VoidAllocator>
int test_map_variants() int test_map_variants()
{ {
@@ -516,7 +525,10 @@ int main()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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 1;
return 0; return 0;

View File

@@ -227,35 +227,6 @@ void test_move()
move_assign.swap(original); 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 boost{
namespace container { namespace container {
namespace test{ namespace test{
@@ -518,6 +489,35 @@ bool test_support_for_initialization_list_for()
return true; 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() int main()
{ {
using namespace boost::container::test; using namespace boost::container::test;
@@ -599,7 +599,10 @@ int main()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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 1;
return 0; return 0;

View File

@@ -150,6 +150,22 @@ bool test_support_for_initializer_list()
return true; 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 () int main ()
{ {
recursive_list_test(); recursive_list_test();
@@ -197,7 +213,7 @@ int main ()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // Allocator propagation testing
//////////////////////////////////// ////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<list>()) if(!boost::container::test::test_propagate_allocator<boost_container_list>())
return 1; return 1;
if(!test_support_for_initializer_list()) if(!test_support_for_initializer_list())

View File

@@ -235,45 +235,6 @@ void test_move()
move_assign.swap(original); 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> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorMap struct GetAllocatorMap
{ {
@@ -389,6 +350,37 @@ bool test_support_for_initialization_list_for()
return true; 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 () int main ()
{ {
//Recursive container instantiation //Recursive container instantiation
@@ -462,7 +454,10 @@ int main ()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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; return 1;
if(!test_support_for_initialization_list_for<map<int, int> >()) if(!test_support_for_initialization_list_for<map<int, int> >())

View File

@@ -20,81 +20,165 @@ namespace boost{
namespace container { namespace container {
namespace test{ 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() bool test_propagate_allocator()
{ {
{ {
typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate; typedef propagation_test_allocator<char, true, true, true, true> AlwaysPropagate;
typedef ContainerWrapper<char, AlwaysPropagate> PropagateCont; typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector> PropagateCont;
typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
////////////////////////////////////////// {
//Test AlwaysPropagate allocator propagation //////////////////////////////////////////
////////////////////////////////////////// //Test AlwaysPropagate allocator propagation
AlwaysPropagate::reset_unique_id(); //////////////////////////////////////////
//default constructor //default constructor
PropagateCont c; StoredAllocator::reset_unique_id(111);
BOOST_TEST (c.get_stored_allocator().id_ == 0); PropagateCont c; //stored 112
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0); BOOST_TEST (c.get_stored_allocator().id_ == 112);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0); BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0); BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0); BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 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). //copy constructor
//For allocators that copy in select_on_container_copy_construction, at least we must have a copy StoredAllocator::reset_unique_id(222);
unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_; PropagateCont c; //stored 223
unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_; BOOST_TEST (c.get_stored_allocator().id_ == 223);
BOOST_TEST (c2.get_stored_allocator().id_ == 0); //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
BOOST_TEST (ctr_copies > 0); //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0); PropagateCont c2(c); //should propagate 223
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0); BOOST_TEST (c2.get_stored_allocator().id_ == 223);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0); BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0); BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
//move constructor BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
PropagateCont c3(boost::move(c2)); BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
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); //move constructor
ctr_moves = c3.get_stored_allocator().ctr_moves_; StoredAllocator::reset_unique_id(333);
BOOST_TEST (ctr_moves > 0); PropagateCont c; //stored 334
BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0); BOOST_TEST (c.get_stored_allocator().id_ == 334);
BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0); PropagateCont c2(boost::move(c)); //should propagate 334
BOOST_TEST (c3.get_stored_allocator().swaps_ == 0); BOOST_TEST (c2.get_stored_allocator().id_ == 334);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
//copy assign BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
c2 = c3; BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
unsigned int assign_copies = c2.get_stored_allocator().assign_copies_; BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().id_ == 0); BOOST_TEST (c2.get_stored_allocator().swaps_ == 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); //copy assign
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0); StoredAllocator::reset_unique_id(444);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0); PropagateCont c; //stored 445
BOOST_TEST (c.get_stored_allocator().id_ == 445);
//move assign PropagateCont c2; //stored 446
c = boost::move(c2); BOOST_TEST (c2.get_stored_allocator().id_ == 446);
unsigned int assign_moves = c.get_stored_allocator().assign_moves_; c2 = c; //should propagate 445
BOOST_TEST (c.get_stored_allocator().id_ == 0); BOOST_TEST (c2.get_stored_allocator().id_ == 445);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == ctr_copies); BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_moves_ == ctr_moves); BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == assign_copies); BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
BOOST_TEST (assign_moves == 1); BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0); BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
}
//swap {
c.get_stored_allocator().id_ = 999; //move assign
c.swap(c2); StoredAllocator::reset_unique_id(555);
unsigned int swaps = c2.get_stored_allocator().swaps_; PropagateCont c; //stored 556
BOOST_TEST (c2.get_stored_allocator().id_ == 999); BOOST_TEST (c.get_stored_allocator().id_ == 556);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == ctr_copies); PropagateCont c2; //stored 557
BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == ctr_moves); BOOST_TEST (c2.get_stored_allocator().id_ == 557);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == assign_copies); c = boost::move(c2); //should propagate 557
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == assign_moves); BOOST_TEST (c.get_stored_allocator().id_ == 557);
BOOST_TEST (swaps == 1); 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 propagation_test_allocator<char, false, false, false, false> NeverPropagate;
typedef ContainerWrapper<char, NeverPropagate> NoPropagateCont; typedef alloc_propagate_wrapper<char, NeverPropagate, Selector> NoPropagateCont;
NeverPropagate::reset_unique_id(); 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 return report_errors() == 0;
NoPropagateCont c; }
BOOST_TEST (c.get_stored_allocator().id_ == 0);
BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 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().ctr_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().assign_copies_ == 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().assign_moves_ == 0);
BOOST_TEST (c.get_stored_allocator().swaps_ == 0); BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
}
//copy constructor {
//propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler) //copy allocator constructor
//For allocators that don't copy in select_on_container_copy_construction we must have a default StoredAllocator::reset_unique_id(999);
//construction Container c;
NoPropagateCont c2(c); //stored_allocator_type could be the same type as allocator_type
unsigned int ctr_copies = c2.get_stored_allocator().ctr_copies_; //so reset it again to get a predictable result
unsigned int ctr_moves = c2.get_stored_allocator().ctr_moves_; allocator_type::reset_unique_id(222);
BOOST_TEST (c2.get_stored_allocator().id_ == 1); Container c2(c, allocator_type()); //should propagate 223
BOOST_TEST (ctr_copies >= 0); BOOST_TEST (c2.get_stored_allocator().id_ == 223);
BOOST_TEST (ctr_moves >= 0); BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0); BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0); BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 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); //move allocator constructor
BOOST_TEST (c3.get_stored_allocator().ctr_copies_ == ctr_copies); StoredAllocator::reset_unique_id(999);
BOOST_TEST (c3.get_stored_allocator().ctr_moves_ > ctr_moves); Container c;
unsigned int ctr_moves2 = ctr_moves; //stored_allocator_type could be the same type as allocator_type
ctr_moves = c3.get_stored_allocator().ctr_moves_; //so reset it again to get a predictable result
BOOST_TEST (c3.get_stored_allocator().assign_copies_ == 0); allocator_type::reset_unique_id(333);
BOOST_TEST (c3.get_stored_allocator().assign_moves_ == 0); Container c2(boost::move(c), allocator_type()); //should propagate 334
BOOST_TEST (c3.get_stored_allocator().swaps_ == 0); BOOST_TEST (c2.get_stored_allocator().id_ == 334);
BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
//copy assign BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
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);
BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 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().assign_moves_ == 0);
BOOST_TEST (c2.get_stored_allocator().swaps_ == 0); BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
} }
return report_errors() == 0;
} }
} //namespace test{ } //namespace test{

View File

@@ -212,37 +212,35 @@ void test_move()
move_assign.swap(original); move_assign.swap(original);
} }
template<class T, class Allocator> struct boost_container_set;
class set_propagate_test_wrapper struct boost_container_multiset;
: public boost::container::set<T, std::less<T>, Allocator
//tree_assoc_defaults namespace boost {
> namespace container {
namespace test {
template<>
struct alloc_propagate_base<boost_container_set>
{ {
BOOST_COPYABLE_AND_MOVABLE(set_propagate_test_wrapper) template <class T, class Allocator>
typedef boost::container::set<T, std::less<T>, Allocator > Base; struct apply
public: {
set_propagate_test_wrapper() typedef boost::container::set<T, std::less<T>, Allocator> type;
: 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<>
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> template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
struct GetAllocatorSet struct GetAllocatorSet
{ {
@@ -427,7 +425,10 @@ int main ()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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; return 1;
if(!test_support_for_initialization_list_for<set<int> >()) if(!test_support_for_initialization_list_for<set<int> >())

View File

@@ -147,6 +147,24 @@ bool test_support_for_initializer_list()
return true; 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 () int main ()
{ {
recursive_slist_test(); recursive_slist_test();
@@ -202,7 +220,7 @@ int main ()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // Allocator propagation testing
//////////////////////////////////// ////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<slist>()) if(!boost::container::test::test_propagate_allocator<boost_container_slist>())
return 1; return 1;
if(!test_support_for_initializer_list()) if(!test_support_for_initializer_list())

View File

@@ -113,6 +113,23 @@ int test_cont_variants()
return 0; 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() int main()
{ {
recursive_vector_test(); recursive_vector_test();
@@ -176,7 +193,7 @@ int main()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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; return 1;
//////////////////////////////////// ////////////////////////////////////

View File

@@ -432,35 +432,22 @@ bool test_expand_bwd()
return test::test_all_expand_bwd<string_type>(); return test::test_all_expand_bwd<string_type>();
} }
template<class T, class Allocator> struct boost_container_string;
class string_propagate_test_wrapper
: public basic_string<T, std::char_traits<T>, Allocator> namespace boost { namespace container { namespace test {
template<>
struct alloc_propagate_base<boost_container_string>
{ {
BOOST_COPYABLE_AND_MOVABLE(string_propagate_test_wrapper) template <class T, class Allocator>
typedef basic_string<T, std::char_traits<T>, Allocator> Base; struct apply
public: {
string_propagate_test_wrapper() typedef boost::container::basic_string<T, std::char_traits<T>, Allocator> type;
: 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); }
}; };
}}} //namespace boost::container::test
int main() int main()
{ {
if(string_test<char>()){ if(string_test<char>()){
@@ -480,7 +467,7 @@ int main()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // 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; return 1;
//////////////////////////////////// ////////////////////////////////////

View File

@@ -145,6 +145,22 @@ int test_cont_variants()
return 0; 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() int main()
{ {
{ {
@@ -235,7 +251,7 @@ int main()
//////////////////////////////////// ////////////////////////////////////
// Allocator propagation testing // Allocator propagation testing
//////////////////////////////////// ////////////////////////////////////
if(!boost::container::test::test_propagate_allocator<vector>()){ if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
return 1; return 1;
} }