diff --git a/doc/container.qbk b/doc/container.qbk index 6f4c114..9e2972f 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1215,9 +1215,11 @@ use [*Boost.Container]? There are several reasons for that: [section:release_notes_boost_1_61_00 Boost 1.61 Release] +* [classref boost::container::small_vector] supports more constructors and assignments. * Fixed bugs: - * [@https://svn.boost.org/trac/boost/ticket/11820 Trac #11820 : ['"compilier error when using operator[] of map"]]. + * [@https://svn.boost.org/trac/boost/ticket/11820 Trac #11820 : ['"compiler error when using operator[] of map"]]. * [@https://svn.boost.org/trac/boost/ticket/11856 Trac #11856 : ['"pool_resource.cpp error: declaration changes meaning"]]. + * [@https://svn.boost.org/trac/boost/ticket/11867 Trac #11867 : ['"small_vector should have constructor and assignment operator taking other small_vector"]]. * [@https://github.com/boostorg/container/pull/33 GitHub #33: ['Make sure std::string constructor is available]]. [endsect] diff --git a/include/boost/container/small_vector.hpp b/include/boost/container/small_vector.hpp index a0115f6..3713d93 100644 --- a/include/boost/container/small_vector.hpp +++ b/include/boost/container/small_vector.hpp @@ -355,9 +355,6 @@ class small_vector_base //~small_vector_base(){} - using base_type::is_propagable_from; - using base_type::steal_resources; - private: //The only member storage_type m_storage_start; @@ -373,6 +370,21 @@ class small_vector_base BOOST_CONTAINER_FORCEINLINE void swap(small_vector_base &other) { return this->base_type::swap(other); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + protected: + void move_construct_impl(base_type &x, const allocator_type &a) + { + if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ + this->steal_resources(x); + } + else{ + this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) + , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ())) + ); + } + } + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -508,6 +520,15 @@ class small_vector : public small_vector_base : base_type(initial_capacity_t(), internal_capacity(), a) { this->assign(other.cbegin(), other.cend()); } + explicit small_vector(const base_type &other) + : base_type( initial_capacity_t(), internal_capacity() + , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator())) + { this->assign(other.cbegin(), other.cend()); } + + explicit small_vector(BOOST_RV_REF(base_type) other) + : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) + { this->move_construct_impl(other, other.get_stored_allocator()); } + small_vector(BOOST_RV_REF(small_vector) other) : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) { this->move_construct_impl(other, other.get_stored_allocator()); } @@ -530,23 +551,14 @@ class small_vector : public small_vector_base BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other) { return static_cast(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } + BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other) + { return static_cast(this->base_type::operator=(other)); } + + BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(base_type) other) + { return static_cast(this->base_type::operator=(boost::move(other))); } + BOOST_CONTAINER_FORCEINLINE void swap(small_vector &other) { return this->base_type::swap(other); } - - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - private: - void move_construct_impl(small_vector &x, const allocator_type &a) - { - if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ - this->steal_resources(x); - } - else{ - this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ())) - ); - } - } - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; }} diff --git a/test/propagate_allocator_test.hpp b/test/propagate_allocator_test.hpp index aefda76..e3a5048 100644 --- a/test/propagate_allocator_test.hpp +++ b/test/propagate_allocator_test.hpp @@ -88,7 +88,7 @@ class alloc_propagate_wrapper {} alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x) - { this->Base::operator=(x); return *this; } + { this->Base::operator=((const Base &)x); return *this; } alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x) { this->Base::operator=(boost::move(static_cast(x))); return *this; } diff --git a/test/small_vector_test.cpp b/test/small_vector_test.cpp index ab03435..bd15590 100644 --- a/test/small_vector_test.cpp +++ b/test/small_vector_test.cpp @@ -96,7 +96,7 @@ bool test_small_vector_base_test() return false; } { - typedef boost::container::small_vector sm7_t; + typedef boost::container::small_vector sm7_t; sm7_t sm7; smb_t &smb = sm7; smb.push_back(2); @@ -105,6 +105,32 @@ bool test_small_vector_base_test() if (!boost::container::test::CheckEqualContainers(sm7, smb)) return false; } + { + typedef boost::container::small_vector sm5_t; + sm5_t sm5; + smb_t &smb = sm5; + smb.push_back(1); + sm5_t sm5_copy(smb); + if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy)) + return false; + smb.push_back(2); + if(smb.size() != 2){ + return false; + } + sm5_copy = smb; + if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy)) + return false; + sm5_t sm5_move(boost::move(smb)); + smb.clear(); + if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy)) + return false; + smb = sm5_copy; + sm5_move = boost::move(smb); + smb.clear(); + if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy)) + return false; + } + return true; }