Fixes #152 ("Tree-based containers have troubles with move-only types")

This commit is contained in:
Ion Gaztañaga
2020-10-31 23:09:52 +01:00
parent 38ea1d7294
commit d4c8bd70ea
4 changed files with 95 additions and 40 deletions

View File

@@ -1342,6 +1342,7 @@ use [*Boost.Container]? There are several reasons for that:
* New [classref boost::container::devector devector] container. * New [classref boost::container::devector devector] container.
* Fixed bugs/issues: * 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/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/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"]]. * [@https://github.com/boostorg/container/issues/159 GitHub #159: ['"pmr::monotonic_buffer_resource crashes on large single allocations"]].

View File

@@ -387,13 +387,14 @@ class RecyclingCloner
: m_holder(holder), m_icont(itree) : m_holder(holder), m_icont(itree)
{} {}
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>) BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, node_t &other, bool_<true>)
{ p->do_move_assign(const_cast<node_t &>(other).get_real_data()); } { p->do_move_assign(other.get_real_data()); }
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>) BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>)
{ p->do_assign(other.get_real_data()); } { p->do_assign(other.get_real_data()); }
node_ptr_type operator()(const node_t &other) const node_ptr_type operator()
(typename dtl::if_c<DoMove, node_t &, const node_t&>::type other) const
{ {
if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){ if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
//First recycle a node (this can't throw) //First recycle a node (this can't throw)
@@ -413,7 +414,7 @@ class RecyclingCloner
BOOST_CATCH_END BOOST_CATCH_END
} }
else{ else{
return m_holder.create_node(other.get_real_data()); return m_holder.create_node(boost::move(other.get_real_data()));
} }
} }

View File

@@ -401,21 +401,48 @@ int map_test_insert(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boo
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
//Swapping test {
MyBoostMap tmpboostemap2; //Swapping test
MyStdMap tmpstdmap2; MyBoostMap tmpboostemap2;
MyBoostMultiMap tmpboostemultimap2; MyStdMap tmpstdmap2;
MyStdMultiMap tmpstdmultimap2; MyBoostMultiMap tmpboostemultimap2;
boostmap.swap(tmpboostemap2); MyStdMultiMap tmpstdmultimap2;
stdmap.swap(tmpstdmap2); boostmap.swap(tmpboostemap2);
boostmultimap.swap(tmpboostemultimap2); stdmap.swap(tmpstdmap2);
stdmultimap.swap(tmpstdmultimap2); boostmultimap.swap(tmpboostemultimap2);
boostmap.swap(tmpboostemap2); stdmultimap.swap(tmpstdmultimap2);
stdmap.swap(tmpstdmap2); boostmap.swap(tmpboostemap2);
boostmultimap.swap(tmpboostemultimap2); stdmap.swap(tmpstdmap2);
stdmultimap.swap(tmpstdmultimap2); boostmultimap.swap(tmpboostemultimap2);
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; stdmultimap.swap(tmpstdmultimap2);
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; 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; return 0;
} }

View File

@@ -112,7 +112,7 @@ int set_test_copyable(boost::container::dtl::true_type)
return 1; return 1;
} }
{ {
//Now, test copy constructor //Now, test copy constructor with allocator
MyBoostSet boostsetcopy(boostset, typename MyBoostSet::allocator_type()); MyBoostSet boostsetcopy(boostset, typename MyBoostSet::allocator_type());
MyStdSet stdsetcopy(stdset); MyStdSet stdsetcopy(stdset);
@@ -347,28 +347,54 @@ int set_test ()
return 1; return 1;
} }
//Swapping test {
MyBoostSet tmpboosteset2; //Swapping test
MyStdSet tmpstdset2; MyBoostSet tmpboosteset2;
MyBoostMultiSet tmpboostemultiset2; MyStdSet tmpstdset2;
MyStdMultiSet tmpstdmultiset2; MyBoostMultiSet tmpboostemultiset2;
boostset.swap(tmpboosteset2); MyStdMultiSet tmpstdmultiset2;
stdset.swap(tmpstdset2); boostset.swap(tmpboosteset2);
boostmultiset.swap(tmpboostemultiset2); stdset.swap(tmpstdset2);
stdmultiset.swap(tmpstdmultiset2); boostmultiset.swap(tmpboostemultiset2);
boostset.swap(tmpboosteset2); stdmultiset.swap(tmpstdmultiset2);
stdset.swap(tmpstdset2); boostset.swap(tmpboosteset2);
boostmultiset.swap(tmpboostemultiset2); stdset.swap(tmpstdset2);
stdmultiset.swap(tmpstdmultiset2); boostmultiset.swap(tmpboostemultiset2);
if(!CheckEqualContainers(boostset, stdset)){ stdmultiset.swap(tmpstdmultiset2);
std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl; if(!CheckEqualContainers(boostset, stdset)){
return 1; std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl;
} return 1;
if(!CheckEqualContainers(boostmultiset, stdmultiset)){ }
std::cout << "Error in boostmultiset.swap(tmpboostemultiset2)" << std::endl; if(!CheckEqualContainers(boostmultiset, stdmultiset)){
return 1; 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 //Insertion from other container
//Initialize values //Initialize values
{ {