From 55d4aaeef5731dd0899b75f2e481fe13ea2ebc27 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Fri, 25 Feb 2022 13:58:09 -0800 Subject: [PATCH 1/2] Update `node_handle_tests` to prove that nodes can be safely transferred between plain maps/sets and their multi- versions --- test/unordered/node_handle_tests.cpp | 138 +++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 6 deletions(-) diff --git a/test/unordered/node_handle_tests.cpp b/test/unordered/node_handle_tests.cpp index 2d5b1eab..89648d0f 100644 --- a/test/unordered/node_handle_tests.cpp +++ b/test/unordered/node_handle_tests.cpp @@ -245,6 +245,49 @@ UNORDERED_AUTO_TEST (node_handle_tests) { node_handle_tests_impl(x2); } +template +typename boost::unordered_map::iterator +insert_empty_node(boost::unordered_map& c) +{ + typedef + typename boost::unordered_map::node_type + node_type; + + return c.insert(node_type()).position; +} + +template +typename boost::unordered_set::iterator +insert_empty_node(boost::unordered_set& c) +{ + typedef typename boost::unordered_set::node_type + node_type; + + return c.insert(node_type()).position; +} + +template +typename boost::unordered_multimap::iterator +insert_empty_node( + boost::unordered_multimap& c) +{ + typedef typename boost::unordered_multimap::node_type node_type; + + return c.insert(node_type()); +} + +template +typename boost::unordered_multiset::iterator +insert_empty_node(boost::unordered_multiset& c) +{ + typedef + typename boost::unordered_multiset::node_type + node_type; + + return c.insert(node_type()); +} + template void insert_node_handle_unique(Container1& c1, Container2& c2) { @@ -253,14 +296,12 @@ void insert_node_handle_unique(Container1& c1, Container2& c2) BOOST_STATIC_ASSERT( (boost::is_same::value)); - typedef typename Container1::insert_return_type insert_return_type1; + typedef typename Container1::iterator iterator1; typedef typename Container2::insert_return_type insert_return_type2; - insert_return_type1 r1 = c1.insert(node_type()); + iterator1 r1 = insert_empty_node(c1); insert_return_type2 r2 = c2.insert(node_type()); - BOOST_TEST(!r1.inserted); - BOOST_TEST(!r1.node); - BOOST_TEST(r1.position == c1.end()); + BOOST_TEST(r1 == c1.end()); BOOST_TEST(!r2.inserted); BOOST_TEST(!r2.node); BOOST_TEST(r2.position == c2.end()); @@ -332,7 +373,7 @@ void insert_node_handle_equiv(Container1& c1, Container2& c2) typedef typename Container1::iterator iterator1; typedef typename Container2::iterator iterator2; - iterator1 r1 = c1.insert(node_type()); + iterator1 r1 = insert_empty_node(c1); iterator2 r2 = c2.insert(node_type()); BOOST_TEST(r1 == c1.end()); BOOST_TEST(r2 == c2.end()); @@ -368,6 +409,17 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) { BOOST_TEST(x2.size() == 3); } + { + boost::unordered_multiset x1; + boost::unordered_set x2; + x1.emplace(100); + x1.emplace(140); + x1.emplace(-55); + x2.emplace(140); + insert_node_handle_unique(x1, x2); + BOOST_TEST(x2.size() == 3); + } + { boost::unordered_map x1; boost::unordered_map x2; @@ -379,6 +431,18 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) { insert_node_handle_unique(x1, x2); BOOST_TEST(x2.size() == 4); } + + { + boost::unordered_multimap x1; + boost::unordered_map x2; + x1.emplace(67, 50); + x1.emplace(23, 45); + x1.emplace(18, 19); + x2.emplace(23, 50); + x2.emplace(12, 49); + insert_node_handle_unique(x1, x2); + BOOST_TEST(x2.size() == 4); + } } UNORDERED_AUTO_TEST (insert_node_handle_equiv_tests) { @@ -394,6 +458,45 @@ UNORDERED_AUTO_TEST (insert_node_handle_equiv_tests) { insert_node_handle_equiv(x1, x2); BOOST_TEST(x2.size() == 6); } + + { + boost::unordered_map x1; + boost::unordered_multimap x2; + x1.emplace(67, 50); + x1.emplace(67, 100); + x1.emplace(23, 45); + x1.emplace(18, 19); + x2.emplace(23, 50); + x2.emplace(12, 49); + insert_node_handle_equiv(x1, x2); + BOOST_TEST(x2.size() == 5); + } + + { + boost::unordered_multiset x1; + boost::unordered_multiset x2; + x1.emplace(67); + x1.emplace(67); + x1.emplace(23); + x1.emplace(18); + x2.emplace(23); + x2.emplace(12); + insert_node_handle_equiv(x1, x2); + BOOST_TEST(x2.size() == 6); + } + + { + boost::unordered_set x1; + boost::unordered_multiset x2; + x1.emplace(67); + x1.emplace(67); + x1.emplace(23); + x1.emplace(18); + x2.emplace(23); + x2.emplace(12); + insert_node_handle_equiv(x1, x2); + BOOST_TEST(x2.size() == 5); + } } UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) { @@ -408,6 +511,17 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) { BOOST_TEST(x2.size() == 3); } + { + boost::unordered_multiset x1; + boost::unordered_set x2; + x1.emplace(100); + x1.emplace(140); + x1.emplace(-55); + x2.emplace(140); + insert_node_handle_unique2(x1, x2); + BOOST_TEST(x2.size() == 3); + } + { boost::unordered_map x1; boost::unordered_map x2; @@ -419,6 +533,18 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) { insert_node_handle_unique2(x1, x2); BOOST_TEST(x2.size() == 4); } + + { + boost::unordered_multimap x1; + boost::unordered_map x2; + x1.emplace(67, 50); + x1.emplace(23, 45); + x1.emplace(18, 19); + x2.emplace(23, 50); + x2.emplace(12, 49); + insert_node_handle_unique2(x1, x2); + BOOST_TEST(x2.size() == 4); + } } RUN_TESTS() From 3fe2c29204ee2ecc29ddc4a117109d5e3c92cb7a Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Fri, 25 Feb 2022 13:59:00 -0800 Subject: [PATCH 2/2] Update documentation on `extract`/`insert` to no longer say that transferring nodes between the corresponding multi- container is not supported --- doc/unordered/unordered_map.adoc | 10 +++++----- doc/unordered/unordered_multimap.adoc | 10 +++++----- doc/unordered/unordered_multiset.adoc | 12 +++++++----- doc/unordered/unordered_set.adoc | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/doc/unordered/unordered_map.adoc b/doc/unordered/unordered_map.adoc index 053657d9..ebf53bf0 100644 --- a/doc/unordered/unordered_map.adoc +++ b/doc/unordered/unordered_map.adoc @@ -871,7 +871,7 @@ Removes the element pointed to by `position`. [horizontal] Returns:;; A `node_type` owning the element. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_multimap`. --- @@ -885,7 +885,7 @@ Removes an element with key equivalent to `k`. [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_multimap`. --- @@ -901,7 +901,7 @@ This overload only participates in overload resolution if `Hash::is_transparent` [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_multimap`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_multimap`. --- @@ -926,7 +926,7 @@ Notes:;; Can invalidate iterators, but only if the insert causes the load factor + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_multimap`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_multimap`. --- @@ -957,7 +957,7 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_multimap`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_multimap`. --- diff --git a/doc/unordered/unordered_multimap.adoc b/doc/unordered/unordered_multimap.adoc index d8eae540..b3b0928c 100644 --- a/doc/unordered/unordered_multimap.adoc +++ b/doc/unordered/unordered_multimap.adoc @@ -846,7 +846,7 @@ Removes the element pointed to by `position`. [horizontal] Returns:;; A `node_type` owning the element. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_map`. --- @@ -860,7 +860,7 @@ Removes an element with key equivalent to `k`. [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_map`. --- @@ -876,7 +876,7 @@ This overload only participates in overload resolution if `Hash::is_transparent` [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_map`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_map`. --- @@ -899,7 +899,7 @@ Notes:;; Can invalidate iterators, but only if the insert causes the load factor + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_map`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_map`. --- @@ -926,7 +926,7 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_map`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_map`. --- diff --git a/doc/unordered/unordered_multiset.adoc b/doc/unordered/unordered_multiset.adoc index 0369673e..f95357fd 100644 --- a/doc/unordered/unordered_multiset.adoc +++ b/doc/unordered/unordered_multiset.adoc @@ -806,7 +806,7 @@ Removes the element pointed to by `position`. [horizontal] Returns:;; A `node_type` owning the element. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_set`. --- @@ -820,7 +820,7 @@ Removes an element with key equivalent to `k`. [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_set`. --- @@ -836,7 +836,7 @@ This overload only participates in overload resolution if `Hash::is_transparent` [horizontal] Returns:;; A `node_type` owning the element if found, otherwise an empty `node_type`. Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`.[horizontal] -Notes:;; In C++17 a node extracted using this method can be inserted into a compatible `unordered_set`, but that is not supported yet. +Notes:;; A node extracted using this method can be inserted into a compatible `unordered_set`. --- @@ -857,7 +857,9 @@ Otherwise returns an iterator pointing to the newly inserted element. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. Notes:;; Can invalidate iterators, but only if the insert causes the load factor to be greater to or equal to the maximum load factor. + + -Pointers and references to elements are never invalidated. In C++17 this can be used to insert a node extracted from a compatible `unordered_set`, but that is not supported yet. +Pointers and references to elements are never invalidated. + ++ +This can be used to insert a node extracted from a compatible `unordered_set`. --- @@ -884,7 +886,7 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_set`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_set`. --- diff --git a/doc/unordered/unordered_set.adoc b/doc/unordered/unordered_set.adoc index 44670457..bc1d39e1 100644 --- a/doc/unordered/unordered_set.adoc +++ b/doc/unordered/unordered_set.adoc @@ -908,7 +908,7 @@ Can invalidate iterators, but only if the insert causes the load factor to be gr + Pointers and references to elements are never invalidated. + + -In C++17 this can be used to insert a node extracted from a compatible `unordered_multiset`, but that is not supported yet. +This can be used to insert a node extracted from a compatible `unordered_multiset`. ---