diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index 55e0771..985bb26 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -349,12 +349,12 @@ struct allocator_traits #endif #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! Returns: a.storage_can_be_propagated(p, to, propagate_a) if is_partially_propagable::value is true; otherwise, - //! a == to. - static bool storage_can_be_propagated(const Allocator &a, pointer p, const Allocator &to, bool propagate_a) BOOST_NOEXCEPT_OR_NOTHROW + //! Returns: a.storage_is_unpropagable(p) if is_partially_propagable::value is true; otherwise, + //! false. + static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW { container_detail::bool_ flag; - return allocator_traits::priv_storage_can_be_propagated(flag, a, p, to, propagate_a); + return allocator_traits::priv_storage_is_unpropagable(flag, a, p); } //! Returns: true if is_always_equal::value == true, otherwise, @@ -471,11 +471,11 @@ struct allocator_traits static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&) { ::new((void*)p) T; } - static bool priv_storage_can_be_propagated(container_detail::true_type, const Allocator &a, pointer p, const Allocator &to, const bool propagate_a) - { return a.storage_can_be_propagated(p, to, propagate_a); } + static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p) + { return a.storage_is_unpropagable(p); } - static bool priv_storage_can_be_propagated(container_detail::false_type, const Allocator &a, pointer, const Allocator &to, const bool propagate_a) - { return allocator_traits::equal(a, to) || propagate_a; } + static bool priv_storage_is_unpropagable(container_detail::false_type, const Allocator &, pointer) + { return false; } static bool priv_equal(container_detail::true_type, const Allocator &, const Allocator &) { return true; } diff --git a/include/boost/container/small_vector.hpp b/include/boost/container/small_vector.hpp index 75f7663..01bbf74 100644 --- a/include/boost/container/small_vector.hpp +++ b/include/boost/container/small_vector.hpp @@ -193,11 +193,8 @@ class small_vector_allocator small_vector_allocator select_on_container_copy_construction() const { return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); } - bool storage_can_be_propagated(pointer p, const small_vector_allocator &to, const bool propagate_a) const - { - return !this->is_internal_storage(p) && - allocator_traits_type::storage_can_be_propagated(this->as_base(), p, to.as_base(), propagate_a); - } + bool storage_is_unpropagable(pointer p) const + { return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); } //!Swaps two allocators, does nothing //!because this small_vector_allocator is stateless @@ -507,7 +504,7 @@ class small_vector : public small_vector_base private: void move_construct_impl(small_vector &x, const allocator_type &a) { - if(base_type::is_propagable_from(x, a, true)){ + if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ this->steal_resources(x); } else{ diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 1cda294..0c6e2ff 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -278,6 +278,23 @@ struct vector_alloc_holder typedef typename allocator_traits_type::size_type size_type; typedef typename allocator_traits_type::value_type value_type; + static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator) + { + (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc; + return (!allocator_traits_type::is_partially_propagable::value || + !allocator_traits_type::storage_is_unpropagable(from_alloc, p)) && + (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc)); + } + + static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator) + { + (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a; + return (!allocator_traits_type::is_partially_propagable::value || + (!allocator_traits_type::storage_is_unpropagable(r_a, r_p) && + !allocator_traits_type::storage_is_unpropagable(l_a, l_p)) + ) && (propagate_allocator || allocator_traits_type::equal(l_a, r_a)); + } + //Constructor, does not throw vector_alloc_holder() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible::value) @@ -335,7 +352,7 @@ struct vector_alloc_holder { allocator_type &this_alloc = this->alloc(); allocator_type &x_alloc = holder.alloc(); - if(allocator_traits_type::storage_can_be_propagated(x_alloc, holder.start(), this_alloc, true)){ + if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){ if(this->m_capacity){ this->alloc().deallocate(this->m_start, this->m_capacity); } @@ -624,8 +641,8 @@ class vector #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef typename container_detail::version::type alloc_version; - boost::container::container_detail::vector_alloc_holder - m_holder; + typedef boost::container::container_detail::vector_alloc_holder alloc_holder_t; + alloc_holder_t m_holder; typedef allocator_traits allocator_traits_type; template friend class vector; @@ -635,25 +652,12 @@ class vector typedef container_detail::vec_iterator const_iterator_impl; protected: - static bool is_propagable_from(const vector &x, const Allocator &a, bool const propagate_allocator) - { - (void)propagate_allocator; - return (allocator_traits_type::is_partially_propagable::value && - allocator_traits_type::storage_can_be_propagated(x.get_stored_allocator(), x.m_holder.start(), a, propagate_allocator)) || - (!allocator_traits_type::is_partially_propagable::value && allocator_traits_type::equal(a, x.get_stored_allocator())); - } + static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator) + { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); } - static bool are_swap_propagable(const vector &l, const vector &r, bool const propagate_allocator) - { - (void)propagate_allocator; - const allocator_type &l_a = l.get_stored_allocator(); - const allocator_type &r_a = r.get_stored_allocator(); - return ( allocator_traits_type::is_partially_propagable::value && - allocator_traits_type::storage_can_be_propagated(r_a, r.m_holder.start(), l_a, propagate_allocator) && - allocator_traits_type::storage_can_be_propagated(l_a, l.m_holder.start(), r_a, propagate_allocator) - ) || - ( !allocator_traits_type::is_partially_propagable::value && allocator_traits_type::equal(l_a, r_a) ); - } + static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p + , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator) + { return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -949,9 +953,11 @@ class vector //! //! Complexity: Constant if a == x.get_allocator(), linear otherwise. vector(BOOST_RV_REF(vector) x, const allocator_type &a) - : m_holder(container_detail::uninitialized_size, a, is_propagable_from(x, a, true) ? 0 : x.size()) + : m_holder( container_detail::uninitialized_size, a + , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size() + ) { - if(is_propagable_from(x, a, true)){ + if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){ this->m_holder.steal_resources(x.m_holder); } else{ @@ -2117,8 +2123,8 @@ class vector allocator_type &x_alloc = x.m_holder.alloc(); const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value; - const bool is_propagable_from_x = is_propagable_from(x, this_alloc, propagate_alloc); - const bool is_propagable_from_t = is_propagable_from(*this, x_alloc, propagate_alloc); + const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc); + const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc, propagate_alloc); const bool are_both_propagable = is_propagable_from_x && is_propagable_from_t; //Resources can be transferred if both allocators are @@ -2187,7 +2193,8 @@ class vector void priv_swap(Vector &x, container_detail::false_type) //version_N { const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value; - if(are_swap_propagable(*this, x, propagate_alloc)){ + if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start() + , x.get_stored_allocator(), this->m_holder.start(), propagate_alloc)){ //Just swap internals this->m_holder.swap_resources(x.m_holder); } diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 53dd273..3f4dff0 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -100,7 +100,7 @@ class ComplexAllocator mutable bool max_size_called_; mutable bool select_on_container_copy_construction_called_; bool construct_called_; - mutable bool storage_can_be_propagated_; + mutable bool storage_is_unpropagable_; typedef T value_type; typedef SimpleSmartPtr pointer; @@ -174,8 +174,8 @@ class ComplexAllocator void construct(U *p, boost::container::default_init_t) { construct_called_ = true; ::new(p)U; } - bool storage_can_be_propagated(pointer p, const ComplexAllocator &, bool) const - { storage_can_be_propagated_ = true; return p ? true : false; } + bool storage_is_unpropagable(pointer p) const + { storage_is_unpropagable_ = true; return !p; } //getters bool allocate_called() const @@ -199,8 +199,8 @@ class ComplexAllocator bool construct_called() const { return construct_called_; } - bool storage_can_be_propagated_called() const - { return storage_can_be_propagated_; } + bool storage_is_unpropagable_called() const + { return storage_is_unpropagable_; } }; class copymovable @@ -422,22 +422,22 @@ int main() SAllocTraits::construct(s_alloc, &c, 0, 1, 2); BOOST_TEST(!c.copymoveconstructed() && !c.moved()); } - //storage_can_be_propagated + //storage_is_unpropagable { SAlloc s_alloc2; - BOOST_TEST(SAllocTraits::storage_can_be_propagated(s_alloc, SAllocTraits::pointer(), s_alloc2, true)); + BOOST_TEST(!SAllocTraits::storage_is_unpropagable(s_alloc, SAllocTraits::pointer())); } { { CAlloc c_alloc2; CAlloc::value_type v; - BOOST_TEST( CAllocTraits::storage_can_be_propagated(c_alloc, CAllocTraits::pointer(&v), c_alloc2, true)); - BOOST_TEST(c_alloc.storage_can_be_propagated_called()); + BOOST_TEST(!CAllocTraits::storage_is_unpropagable(c_alloc, CAllocTraits::pointer(&v))); + BOOST_TEST(c_alloc.storage_is_unpropagable_called()); } { CAlloc c_alloc2; - BOOST_TEST(!CAllocTraits::storage_can_be_propagated(c_alloc2, CAllocTraits::pointer(), c_alloc, true)); - BOOST_TEST(c_alloc2.storage_can_be_propagated_called()); + BOOST_TEST( CAllocTraits::storage_is_unpropagable(c_alloc2, CAllocTraits::pointer())); + BOOST_TEST(c_alloc2.storage_is_unpropagable_called()); } }