diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index cd14491..d251c35 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -141,6 +141,9 @@ class flat_map ::pointer>::reverse_iterator reverse_iterator_impl; typedef typename container_detail::get_flat_tree_iterators ::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 ::pointer>::reverse_iterator reverse_iterator_impl; typedef typename container_detail::get_flat_tree_iterators ::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 -#endif /* BOOST_CONTAINER_FLAT_MAP_HPP */ +#endif // BOOST_CONTAINER_FLAT_MAP_HPP diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 3924fb0..4cf2e00 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -1346,4 +1346,4 @@ namespace container { #include -#endif /* BOOST_CONTAINER_FLAT_SET_HPP */ +#endif // BOOST_CONTAINER_FLAT_SET_HPP diff --git a/test/deque_test.cpp b/test/deque_test.cpp index ff31e50..6d37b86 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -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 +{ + template + struct apply + { + typedef boost::container::deque type; + }; +}; + +}}} //namespace boost::container::test + int main () { if(!do_test()) @@ -434,7 +450,7 @@ int main () //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()) + if(!boost::container::test::test_propagate_allocator()) return 1; return 0; diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index 538bf7e..a9f0b82 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -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]; } diff --git a/test/flat_map_test.cpp b/test/flat_map_test.cpp index e55a9ef..f21dddf 100644 --- a/test/flat_map_test.cpp +++ b/test/flat_map_test.cpp @@ -199,40 +199,6 @@ void test_move() move_assign.swap(original); } -template -class flat_map_propagate_test_wrapper - : public boost::container::flat_map - < T, T, std::less - , typename boost::container::allocator_traits::template - portable_rebind_alloc< std::pair >::type> -{ - BOOST_COPYABLE_AND_MOVABLE(flat_map_propagate_test_wrapper) - typedef boost::container::flat_map - < T, T, std::less - , typename boost::container::allocator_traits::template - portable_rebind_alloc< std::pair >::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(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(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 +{ + template + struct apply + { + typedef typename boost::container::allocator_traits:: + template portable_rebind_alloc >::type TypeAllocator; + typedef boost::container::flat_map, TypeAllocator> type; + }; +}; + +template<> +struct alloc_propagate_base +{ + template + struct apply + { + typedef typename boost::container::allocator_traits:: + template portable_rebind_alloc >::type TypeAllocator; + typedef boost::container::flat_multimap, TypeAllocator> type; + }; +}; + +template +struct get_real_stored_allocator > +{ + typedef typename flat_map::impl_stored_allocator_type type; +}; + +template +struct get_real_stored_allocator > +{ + typedef typename flat_multimap::impl_stored_allocator_type type; +}; + +}}} //namespace boost::container::test + template int test_map_variants() { @@ -516,7 +525,10 @@ int main() //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()) + if(!boost::container::test::test_propagate_allocator()) + return 1; + + if(!boost::container::test::test_propagate_allocator()) return 1; return 0; diff --git a/test/flat_set_test.cpp b/test/flat_set_test.cpp index bd39ff8..f78c223 100644 --- a/test/flat_set_test.cpp +++ b/test/flat_set_test.cpp @@ -227,35 +227,6 @@ void test_move() move_assign.swap(original); } -template -class flat_set_propagate_test_wrapper - : public boost::container::flat_set, Allocator> -{ - BOOST_COPYABLE_AND_MOVABLE(flat_set_propagate_test_wrapper) - typedef boost::container::flat_set, 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(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(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 +{ + template + struct apply + { + typedef boost::container::flat_set, Allocator> type; + }; +}; + +template<> +struct alloc_propagate_base +{ + template + struct apply + { + typedef boost::container::flat_multiset, 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()) + if(!boost::container::test::test_propagate_allocator()) + return 1; + + if(!boost::container::test::test_propagate_allocator()) return 1; return 0; diff --git a/test/list_test.cpp b/test/list_test.cpp index 46cc22e..cea84bd 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -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 +{ + template + struct apply + { + typedef boost::container::list 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()) + if(!boost::container::test::test_propagate_allocator()) return 1; if(!test_support_for_initializer_list()) diff --git a/test/map_test.cpp b/test/map_test.cpp index a98016f..ed27924 100644 --- a/test/map_test.cpp +++ b/test/map_test.cpp @@ -235,45 +235,6 @@ void test_move() move_assign.swap(original); } -template -class map_propagate_test_wrapper - : public boost::container::map - < T, T, std::less - , typename boost::container::allocator_traits::template - portable_rebind_alloc< std::pair >::type - //tree_assoc_defaults - > -{ - BOOST_COPYABLE_AND_MOVABLE(map_propagate_test_wrapper) - typedef boost::container::map - < T, T, std::less - , typename boost::container::allocator_traits::template - portable_rebind_alloc< std::pair >::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(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(x))); return *this; } - - void swap(map_propagate_test_wrapper &x) - { this->Base::swap(x); } -}; - - template 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 +{ + template + struct apply + { + typedef typename boost::container::allocator_traits:: + template portable_rebind_alloc >::type TypeAllocator; + typedef boost::container::map, TypeAllocator> type; + }; +}; + +template<> +struct alloc_propagate_base +{ + template + struct apply + { + typedef typename boost::container::allocator_traits:: + template portable_rebind_alloc >::type TypeAllocator; + typedef boost::container::multimap, 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()) + if(!boost::container::test::test_propagate_allocator()) + return 1; + + if(!boost::container::test::test_propagate_allocator()) return 1; if(!test_support_for_initialization_list_for >()) diff --git a/test/propagate_allocator_test.hpp b/test/propagate_allocator_test.hpp index 6713889..6aacea2 100644 --- a/test/propagate_allocator_test.hpp +++ b/test/propagate_allocator_test.hpp @@ -20,81 +20,165 @@ namespace boost{ namespace container { namespace test{ -template class ContainerWrapper> +template +struct alloc_propagate_base; + +template +class alloc_propagate_wrapper + : public alloc_propagate_base::template apply::type +{ + BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper) + + public: + typedef typename alloc_propagate_base + ::template apply::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(x))) + {} + + alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a) + : Base(boost::move(static_cast(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(x))); return *this; } + + void swap(alloc_propagate_wrapper &x) + { this->Base::swap(x); } +}; + +template +struct get_real_stored_allocator +{ + typedef typename T::stored_allocator_type type; +}; + +template +void test_propagate_allocator_allocator_arg(); + +template bool test_propagate_allocator() { { typedef propagation_test_allocator AlwaysPropagate; - typedef ContainerWrapper 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 PropagateCont; + typedef typename get_real_stored_allocator::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(); } ////////////////////////////////////////// @@ -102,74 +186,149 @@ bool test_propagate_allocator() ////////////////////////////////////////// { typedef propagation_test_allocator NeverPropagate; - typedef ContainerWrapper NoPropagateCont; - NeverPropagate::reset_unique_id(); + typedef alloc_propagate_wrapper NoPropagateCont; + typedef typename get_real_stored_allocator::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(); + } - //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 +void test_propagate_allocator_allocator_arg() +{ + typedef typename Container::allocator_type allocator_type; + typedef typename get_real_stored_allocator::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{ diff --git a/test/set_test.cpp b/test/set_test.cpp index 656305b..9eb3157 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -212,37 +212,35 @@ void test_move() move_assign.swap(original); } -template -class set_propagate_test_wrapper - : public boost::container::set, Allocator - //tree_assoc_defaults - > +struct boost_container_set; +struct boost_container_multiset; + +namespace boost { +namespace container { +namespace test { + +template<> +struct alloc_propagate_base { - BOOST_COPYABLE_AND_MOVABLE(set_propagate_test_wrapper) - typedef boost::container::set, 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(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(x))); return *this; } - - void swap(set_propagate_test_wrapper &x) - { this->Base::swap(x); } + template + struct apply + { + typedef boost::container::set, Allocator> type; + }; }; +template<> +struct alloc_propagate_base +{ + template + struct apply + { + typedef boost::container::multiset, Allocator> type; + }; +}; + +}}} //boost::container::test + template struct GetAllocatorSet { @@ -427,7 +425,10 @@ int main () //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()) + if(!boost::container::test::test_propagate_allocator()) + return 1; + + if(!boost::container::test::test_propagate_allocator()) return 1; if(!test_support_for_initialization_list_for >()) diff --git a/test/slist_test.cpp b/test/slist_test.cpp index f5420c5..7c58fb0 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -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 +{ + template + struct apply + { + typedef boost::container::slist type; + }; +}; + +}}} + int main () { recursive_slist_test(); @@ -202,7 +220,7 @@ int main () //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()) + if(!boost::container::test::test_propagate_allocator()) return 1; if(!test_support_for_initializer_list()) diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index ecc6c55..afc998f 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -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 +{ + template + struct apply + { + typedef boost::container::stable_vector 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()) + if(!boost::container::test::test_propagate_allocator()) return 1; //////////////////////////////////// diff --git a/test/string_test.cpp b/test/string_test.cpp index 7d63e8d..2e3f670 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -432,35 +432,22 @@ bool test_expand_bwd() return test::test_all_expand_bwd(); } -template -class string_propagate_test_wrapper - : public basic_string, Allocator> +struct boost_container_string; + +namespace boost { namespace container { namespace test { + +template<> +struct alloc_propagate_base { - BOOST_COPYABLE_AND_MOVABLE(string_propagate_test_wrapper) - typedef basic_string, 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(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(x))); return *this; } - - void swap(string_propagate_test_wrapper &x) - { this->Base::swap(x); } + template + struct apply + { + typedef boost::container::basic_string, Allocator> type; + }; }; +}}} //namespace boost::container::test + int main() { if(string_test()){ @@ -480,7 +467,7 @@ int main() //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()) + if(!boost::container::test::test_propagate_allocator()) return 1; //////////////////////////////////// diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 0c62cf2..b840262 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -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 +{ + template + struct apply + { + typedef boost::container::vector type; + }; +}; + +}}} //namespace boost::container::test + int main() { { @@ -235,7 +251,7 @@ int main() //////////////////////////////////// // Allocator propagation testing //////////////////////////////////// - if(!boost::container::test::test_propagate_allocator()){ + if(!boost::container::test::test_propagate_allocator()){ return 1; }