diff --git a/doc/container.qbk b/doc/container.qbk index 3293791..0cda76c 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1342,6 +1342,7 @@ use [*Boost.Container]? There are several reasons for that: * New [classref boost::container::devector devector] container. * Fixed bugs/issues: + * [@https://github.com/boostorg/container/issues/152 GitHub #152: ['"Tree-based containers have troubles with move-only types"]]. * [@https://github.com/boostorg/container/issues/156 GitHub #156: ['"Compile error with vector"]]. * [@https://github.com/boostorg/container/pull/157 GitHub #157: ['"Add missing include"]]. * [@https://github.com/boostorg/container/issues/159 GitHub #159: ['"pmr::monotonic_buffer_resource crashes on large single allocations"]]. diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 23fbfde..e8df720 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -387,13 +387,14 @@ class RecyclingCloner : m_holder(holder), m_icont(itree) {} - BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_) - { p->do_move_assign(const_cast(other).get_real_data()); } + BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, node_t &other, bool_) + { p->do_move_assign(other.get_real_data()); } BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_) { p->do_assign(other.get_real_data()); } - node_ptr_type operator()(const node_t &other) const + node_ptr_type operator() + (typename dtl::if_c::type other) const { if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){ //First recycle a node (this can't throw) @@ -413,7 +414,7 @@ class RecyclingCloner BOOST_CATCH_END } else{ - return m_holder.create_node(other.get_real_data()); + return m_holder.create_node(boost::move(other.get_real_data())); } } diff --git a/test/map_test.hpp b/test/map_test.hpp index 160c46a..d3ce4cb 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -401,21 +401,48 @@ int map_test_insert(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boo if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; - //Swapping test - MyBoostMap tmpboostemap2; - MyStdMap tmpstdmap2; - MyBoostMultiMap tmpboostemultimap2; - MyStdMultiMap tmpstdmultimap2; - boostmap.swap(tmpboostemap2); - stdmap.swap(tmpstdmap2); - boostmultimap.swap(tmpboostemultimap2); - stdmultimap.swap(tmpstdmultimap2); - boostmap.swap(tmpboostemap2); - stdmap.swap(tmpstdmap2); - boostmultimap.swap(tmpboostemultimap2); - stdmultimap.swap(tmpstdmultimap2); - if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; - if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + { + //Swapping test + MyBoostMap tmpboostemap2; + MyStdMap tmpstdmap2; + MyBoostMultiMap tmpboostemultimap2; + MyStdMultiMap tmpstdmultimap2; + boostmap.swap(tmpboostemap2); + stdmap.swap(tmpstdmap2); + boostmultimap.swap(tmpboostemultimap2); + stdmultimap.swap(tmpstdmultimap2); + boostmap.swap(tmpboostemap2); + stdmap.swap(tmpstdmap2); + boostmultimap.swap(tmpboostemultimap2); + stdmultimap.swap(tmpstdmultimap2); + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + + //move constructor/assignment + { + MyBoostMap tmpboostemap2(boost::move(boostmap)); + if(!CheckEqualContainers(tmpboostemap2, stdmap)){ + std::cout << "Error in boostmap move constructor" << std::endl; + return 1; + } + MyBoostMultiMap tmpboostemultimap2(boost::move(boostmultimap)); + if(!CheckEqualContainers(tmpboostemultimap2, stdmultimap)){ + std::cout << "Error in boostmultimap move constructor" << std::endl; + return 1; + } + + boostmap = boost::move(tmpboostemap2); + if(!CheckEqualContainers(boostmap, stdmap)){ + std::cout << "Error in boostmap move assignment" << std::endl; + return 1; + } + boostmultimap = boost::move(tmpboostemultimap2); + if(!CheckEqualContainers(boostmultimap, stdmultimap)){ + std::cout << "Error in boostmultimap move assignment" << std::endl; + return 1; + } + } } return 0; } diff --git a/test/set_test.hpp b/test/set_test.hpp index 7bc3a09..8d12fe8 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -112,7 +112,7 @@ int set_test_copyable(boost::container::dtl::true_type) return 1; } { - //Now, test copy constructor + //Now, test copy constructor with allocator MyBoostSet boostsetcopy(boostset, typename MyBoostSet::allocator_type()); MyStdSet stdsetcopy(stdset); @@ -347,28 +347,54 @@ int set_test () return 1; } - //Swapping test - MyBoostSet tmpboosteset2; - MyStdSet tmpstdset2; - MyBoostMultiSet tmpboostemultiset2; - MyStdMultiSet tmpstdmultiset2; - boostset.swap(tmpboosteset2); - stdset.swap(tmpstdset2); - boostmultiset.swap(tmpboostemultiset2); - stdmultiset.swap(tmpstdmultiset2); - boostset.swap(tmpboosteset2); - stdset.swap(tmpstdset2); - boostmultiset.swap(tmpboostemultiset2); - stdmultiset.swap(tmpstdmultiset2); - if(!CheckEqualContainers(boostset, stdset)){ - std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl; - return 1; - } - if(!CheckEqualContainers(boostmultiset, stdmultiset)){ - std::cout << "Error in boostmultiset.swap(tmpboostemultiset2)" << std::endl; - return 1; + { + //Swapping test + MyBoostSet tmpboosteset2; + MyStdSet tmpstdset2; + MyBoostMultiSet tmpboostemultiset2; + MyStdMultiSet tmpstdmultiset2; + boostset.swap(tmpboosteset2); + stdset.swap(tmpstdset2); + boostmultiset.swap(tmpboostemultiset2); + stdmultiset.swap(tmpstdmultiset2); + boostset.swap(tmpboosteset2); + stdset.swap(tmpstdset2); + boostmultiset.swap(tmpboostemultiset2); + stdmultiset.swap(tmpstdmultiset2); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl; + return 1; + } + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset.swap(tmpboostemultiset2)" << std::endl; + return 1; + } } + //move constructor/assignment + { + MyBoostSet tmpboosteset2(boost::move(boostset)); + if(!CheckEqualContainers(tmpboosteset2, stdset)){ + std::cout << "Error in boostset move constructor " << std::endl; + return 1; + } + MyBoostMultiSet tmpboostemultiset2(boost::move(boostmultiset)); + if(!CheckEqualContainers(tmpboostemultiset2, stdmultiset)){ + std::cout << "Error in boostmultiset move constructor" << std::endl; + return 1; + } + + boostset = boost::move(tmpboosteset2); + if(!CheckEqualContainers(boostset, stdset)){ + std::cout << "Error in boostset move assignment" << std::endl; + return 1; + } + boostmultiset = boost::move(tmpboostemultiset2); + if(!CheckEqualContainers(boostmultiset, stdmultiset)){ + std::cout << "Error in boostmultiset move assignment" << std::endl; + return 1; + } + } //Insertion from other container //Initialize values {