From a331d3387ff9a23c70a05fc282ae54fe81d2cd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Jun 2024 14:32:56 +0200 Subject: [PATCH 1/9] Include detail/is_pair.hpp since forward declares boost::tuples::tuple --- include/boost/container/detail/pair.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index 190af3a..0e84ffb 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include //Forward declares boost::tuples::tuple #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) # include #endif From 7c9fb0d764789ebaa805dd0c21a5de0f941bf6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Jun 2024 14:36:18 +0200 Subject: [PATCH 2/9] Include pair.hpp since dtl::pair is used --- include/boost/container/detail/node_alloc_holder.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 9343cb6..96680dd 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -38,6 +38,7 @@ #include #include #include +#include // intrusive #include #include From acd4f41edacac3db3721ed1ab4f70e074ed10dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Jun 2024 22:46:23 +0200 Subject: [PATCH 3/9] Remove unneeded header --- include/boost/container/detail/flat_tree.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 93cdb61..1547ad6 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -26,7 +26,6 @@ #include -#include #include #include From d1d8c43c2d933875fd366097659345da1817b66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 13 Jun 2024 22:46:37 +0200 Subject: [PATCH 4/9] Add detail/pair header --- include/boost/container/flat_map.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 7ebfc43..390f0f0 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -31,6 +31,7 @@ #include #include //equal() #include +#include // move #include #include @@ -44,6 +45,7 @@ #include //pair #include //less, equal + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include #endif @@ -1671,9 +1673,8 @@ class flat_map iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. if (i == end() || key_comp()(k, (*i).first)){ - dtl::value_init m; - impl_value_type v(k, ::boost::move(m.m_t)); - i = this->insert(i, ::boost::move(v)); + impl_value_type v(k, mapped_type()); + i = this->m_flat_tree.insert_equal(::boost::move(v)); } return (*i).second; } @@ -1682,10 +1683,9 @@ class flat_map key_type &k = mk; iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. - if (i == end() || key_comp()(k, (*i).first)){ - dtl::value_init m; - impl_value_type v(::boost::move(k), ::boost::move(m.m_t)); - i = this->insert(i, ::boost::move(v)); + if (i == end() || key_comp()(k, (*i).first)) { + impl_value_type v(boost::move(k), mapped_type()); + i = this->m_flat_tree.insert_equal(::boost::move(v)); } return (*i).second; } @@ -1765,7 +1765,7 @@ flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, A template struct has_trivial_destructor_after_move > { - typedef ::boost::container::dtl::pair value_t; + typedef typename boost::container::flat_map::value_type value_t; typedef typename ::boost::container::dtl::container_or_allocator_rebind::type alloc_or_cont_t; typedef ::boost::container::dtl::flat_tree, Compare, alloc_or_cont_t> tree; BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move::value; @@ -3099,7 +3099,7 @@ namespace boost { template struct has_trivial_destructor_after_move< boost::container::flat_multimap > { - typedef ::boost::container::dtl::pair value_t; + typedef typename boost::container::flat_multimap::value_type value_t; typedef typename ::boost::container::dtl::container_or_allocator_rebind::type alloc_or_cont_t; typedef ::boost::container::dtl::flat_tree, Compare, alloc_or_cont_t> tree; BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move::value; From f21c5fb72310498032ac779c4f47442e35d86c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 14 Jun 2024 12:35:23 +0200 Subject: [PATCH 5/9] Add missing detail/pair.hpp include --- test/flat_tree_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 67f2558..6be6f3a 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include From 43ac22eff2a0d8668aa577d42af91024d9258a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 14 Jun 2024 12:36:36 +0200 Subject: [PATCH 6/9] Add test for move assignable index operator --- test/map_test.hpp | 98 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/test/map_test.hpp b/test/map_test.hpp index 0055f57..dd3ecc9 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -865,8 +865,9 @@ int map_test_search(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boo template -int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) + , class MyStdMultiMap + , class Other> +int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap, boost::container::dtl::true_type, Other) { typedef typename MyBoostMap::key_type IntType; typedef dtl::pair IntPairType; @@ -883,18 +884,102 @@ int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &b IntType i2(i); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); } -/* + for(int i = 0; i < MaxElem; ++i){ boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second); stdmap[i] = i; } -*/ + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; } return 0; } +template +int map_test_indexing_move_assignable(MyBoostMap& boostmap, MyStdMap& stdmap, MyBoostMultiMap& boostmultimap, MyStdMultiMap& stdmultimap, boost::container::dtl::true_type) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair IntPairType; + + { //operator[] test + boostmap.clear(); + boostmultimap.clear(); + stdmap.clear(); + stdmultimap.clear(); + + IntPairType aux_vect[(std::size_t)MaxElem]; + for (int i = 0; i < MaxElem; ++i) { + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for (int i = 0; i < MaxElem; ++i) { + boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second); + stdmap[i] = i; + } + + if (!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if (!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + return 0; +} + +template +int map_test_indexing_copyable(MyBoostMap& boostmap, MyStdMap& stdmap, MyBoostMultiMap& boostmultimap, MyStdMultiMap& stdmultimap, boost::container::dtl::true_type) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair IntPairType; + + { //operator[] test + boostmap.clear(); + boostmultimap.clear(); + stdmap.clear(); + stdmultimap.clear(); + + IntPairType aux_vect[(std::size_t)MaxElem]; + for (int i = 0; i < MaxElem; ++i) { + IntType i1(i); + IntType i2(i); + new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); + } + + for (int i = 0; i < MaxElem; ++i) { + boostmap[aux_vect[i].first] = boost::move(aux_vect[i].second); + stdmap[i] = i; + } + + if (!CheckEqualPairContainers(boostmap, stdmap)) return 1; + if (!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; + } + return 0; +} + +template +int map_test_indexing_move_assignable(MyBoostMap& , MyStdMap& , MyBoostMultiMap& , MyStdMultiMap&, boost::container::dtl::false_type) +{ + return 0; +} + +template +int map_test_indexing_copyable(MyBoostMap&, MyStdMap&, MyBoostMultiMap&, MyStdMultiMap&, boost::container::dtl::false_type) +{ + return 0; +} + template< class MyBoostMap, class StdMap, class MaybeMove> int map_test_insert_or_assign_impl() { @@ -1252,7 +1337,10 @@ int map_test() if (map_test_search(boostmap, stdmap, boostmultimap, stdmultimap)) return 1; - if (map_test_indexing(boostmap, stdmap, boostmultimap, stdmultimap)) + if (map_test_indexing_move_assignable(boostmap, stdmap, boostmultimap, stdmultimap, move_assignable_t())) + return 1; + + if (map_test_indexing_copyable(boostmap, stdmap, boostmultimap, stdmultimap, copyable_t())) return 1; if (map_test_try_emplace(boostmap, stdmap, boostmultimap, stdmultimap)) From 2d097fe45cb665a7a642aad1aeaf1521c6eb4e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 14 Jun 2024 12:37:12 +0200 Subject: [PATCH 7/9] Roll back and use dtl::value_init to maximize compatibility between std versions --- include/boost/container/flat_map.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 390f0f0..9a8abb8 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -1673,8 +1673,9 @@ class flat_map iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. if (i == end() || key_comp()(k, (*i).first)){ - impl_value_type v(k, mapped_type()); - i = this->m_flat_tree.insert_equal(::boost::move(v)); + dtl::value_init m; + impl_value_type v(k, ::boost::move(m.m_t)); + i = dtl::force_copy(this->m_flat_tree.insert_equal(::boost::move(v))); } return (*i).second; } @@ -1684,8 +1685,9 @@ class flat_map iterator i = this->lower_bound(k); // i->first is greater than or equivalent to k. if (i == end() || key_comp()(k, (*i).first)) { - impl_value_type v(boost::move(k), mapped_type()); - i = this->m_flat_tree.insert_equal(::boost::move(v)); + dtl::value_init m; + impl_value_type v(::boost::move(k), ::boost::move(m.m_t)); + i = dtl::force_copy(this->m_flat_tree.insert_equal(::boost::move(v))); } return (*i).second; } From a070ce232528694f05266214fc07afcdab4e701d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 14 Jun 2024 13:38:50 +0200 Subject: [PATCH 8/9] Fixes #245 ("flat_tree::insert ordered range doesn't assert sorting") --- include/boost/container/detail/flat_tree.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 1547ad6..b356e94 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -954,6 +954,7 @@ class flat_tree template void insert_equal(ordered_range_t, InIt first, InIt last) { + BOOST_ASSERT((is_sorted)(first, last, this->priv_value_comp())); const bool value = boost::container::dtl:: has_member_function_callable_with_merge_unique::value; (flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_()); @@ -962,6 +963,7 @@ class flat_tree template void insert_unique(ordered_unique_range_t, InIt first, InIt last) { + BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); const bool value = boost::container::dtl:: has_member_function_callable_with_merge_unique::value; (flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_()); From 4025288928adb76ca11380452544907846324ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 14 Jun 2024 13:39:15 +0200 Subject: [PATCH 9/9] Update changelog with #266 and #245 --- doc/container.qbk | 3 ++- proj/vs/explicit_inst_flat_map_test.vcxproj | 2 +- proj/vs/flat_map_test.vcxproj | 2 +- proj/vs/flat_tree_test.vcxproj | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/container.qbk b/doc/container.qbk index ce5479a..b00ea1d 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1418,7 +1418,8 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/issues/275 GitHub #275: ['"Compilation fails if custom key comparison is used"]]. * [@https://github.com/boostorg/container/issues/273 GitHub #273: ['"flat_map/vector crashes on appends (memory corruption)"]]. * [@https://github.com/boostorg/container/issues/269 GitHub #269: ['"flat_multimap::emplace not sorting elements under GCC"]]. - * [@https://github.com/boostorg/container/issues/269 GitHub #269: ['"flat_multimap::emplace not sorting elements under GCC"]]. + * [@https://github.com/boostorg/container/issues/266 GitHub #266: ['"small_vector is misaligned on the stack in 32 bits"]]. + * [@https://github.com/boostorg/container/issues/245 GitHub #245: ['"flat_tree::insert ordered range doesn't assert sorting"]]. [endsect] diff --git a/proj/vs/explicit_inst_flat_map_test.vcxproj b/proj/vs/explicit_inst_flat_map_test.vcxproj index 84afd8b..0817fd5 100644 --- a/proj/vs/explicit_inst_flat_map_test.vcxproj +++ b/proj/vs/explicit_inst_flat_map_test.vcxproj @@ -36,7 +36,7 @@ Application - v143 + v90 MultiByte diff --git a/proj/vs/flat_map_test.vcxproj b/proj/vs/flat_map_test.vcxproj index 8fa0f8f..c5d917f 100644 --- a/proj/vs/flat_map_test.vcxproj +++ b/proj/vs/flat_map_test.vcxproj @@ -36,7 +36,7 @@ Application - v143 + v90 MultiByte diff --git a/proj/vs/flat_tree_test.vcxproj b/proj/vs/flat_tree_test.vcxproj index a9f2c41..c6a32a8 100644 --- a/proj/vs/flat_tree_test.vcxproj +++ b/proj/vs/flat_tree_test.vcxproj @@ -36,7 +36,7 @@ Application - v143 + ClangCL MultiByte