From 164cbe4e0ffbb870811a1f172af07b527bdc3ddc Mon Sep 17 00:00:00 2001 From: joaquintides Date: Sat, 31 May 2025 18:08:37 +0200 Subject: [PATCH] documented non-const reference passing to `erase_if` (#312) * documented non-const reference passing to erase_if * prevented warning as error in Boost.Container build * skipped tests for MinGW (https://github.com/boostorg/atomic/pull/70) * correct reference link for previous commit is https://github.com/boostorg/atomic/issues/73 * commented previous disabled cases * disabled cfoa_serialization_tests with TSAN * fixed previous * fixed previous * fixed previous --- .../pages/reference/concurrent_flat_map.adoc | 8 +++-- .../pages/reference/concurrent_node_map.adoc | 8 +++-- .../pages/reference/unordered_flat_map.adoc | 2 ++ .../ROOT/pages/reference/unordered_map.adoc | 4 ++- .../pages/reference/unordered_multimap.adoc | 2 ++ .../pages/reference/unordered_node_map.adoc | 2 ++ test/Jamfile.v2 | 10 ++++++- test/unordered/erase_if.cpp | 30 +++++++++++++++++++ 8 files changed, 58 insertions(+), 8 deletions(-) diff --git a/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc b/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc index 8fada0a8..42746f06 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc @@ -1429,7 +1429,9 @@ Erases the element `x` with key equivalent to `k` if it exists and `f(x)` is `tr [horizontal] Returns:;; The number of elements erased (0 or 1). Throws:;; Only throws an exception if it is thrown by `hasher`, `key_equal` or `f`. -Notes:;; The `template` overload only participates in overload resolution if `std::is_execution_policy_v>` is `false`. + +Notes:;; `f` is passed a non-const reference to `x`. + ++ +The `template` overload only participates in overload resolution if `std::is_execution_policy_v>` is `false`. + + The `template` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. @@ -1440,7 +1442,7 @@ The `template` overload only participates in overload resoluti template size_type erase_if(F f); ``` -Successively invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`. +Successively invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`. [horizontal] Returns:;; The number of elements erased. @@ -1453,7 +1455,7 @@ Throws:;; Only throws an exception if it is thrown by `f`. template void erase_if(ExecutionPolicy&& policy, F f); ``` -Invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`. +Invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`. Execution is parallelized according to the semantics of the execution policy specified. [horizontal] diff --git a/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc b/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc index 69559ae2..78e63f6e 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc @@ -1519,7 +1519,9 @@ Erases the element `x` with key equivalent to `k` if it exists and `f(x)` is `tr [horizontal] Returns:;; The number of elements erased (0 or 1). Throws:;; Only throws an exception if it is thrown by `hasher`, `key_equal` or `f`. -Notes:;; The `template` overload only participates in overload resolution if `std::is_execution_policy_v>` is `false`. + +Notes:;; `f` is passed a non-const reference to `x`. + ++ +The `template` overload only participates in overload resolution if `std::is_execution_policy_v>` is `false`. + + The `template` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. @@ -1530,7 +1532,7 @@ The `template` overload only participates in overload resoluti template size_type erase_if(F f); ``` -Successively invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`. +Successively invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`. [horizontal] Returns:;; The number of elements erased. @@ -1543,7 +1545,7 @@ Throws:;; Only throws an exception if it is thrown by `f`. template void erase_if(ExecutionPolicy&& policy, F f); ``` -Invokes `f` with references to each of the elements in the table, and erases those for which `f` returns `true`. +Invokes `f` with non-const references to each of the elements in the table, and erases those for which `f` returns `true`. Execution is parallelized according to the semantics of the execution policy specified. [horizontal] diff --git a/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc b/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc index a0357a87..62a1e6f5 100644 --- a/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc @@ -1514,6 +1514,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) { } return original_size - c.size(); ``` ++ +Note that the references passed to `pred` are non-const. === Serialization diff --git a/doc/modules/ROOT/pages/reference/unordered_map.adoc b/doc/modules/ROOT/pages/reference/unordered_map.adoc index ce4d2367..3422b1df 100644 --- a/doc/modules/ROOT/pages/reference/unordered_map.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_map.adoc @@ -1766,7 +1766,9 @@ for (auto i = c.begin(), last = c.end(); i != last; ) { } } return original_size - c.size(); -``` +``` ++ +Note that the references passed to `pred` are non-const. === Serialization diff --git a/doc/modules/ROOT/pages/reference/unordered_multimap.adoc b/doc/modules/ROOT/pages/reference/unordered_multimap.adoc index b0f4dee5..0412a179 100644 --- a/doc/modules/ROOT/pages/reference/unordered_multimap.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_multimap.adoc @@ -1486,6 +1486,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) { } return original_size - c.size(); ``` ++ +Note that the references passed to `pred` are non-const. === Serialization diff --git a/doc/modules/ROOT/pages/reference/unordered_node_map.adoc b/doc/modules/ROOT/pages/reference/unordered_node_map.adoc index 6cae4a4b..88a05a25 100644 --- a/doc/modules/ROOT/pages/reference/unordered_node_map.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_node_map.adoc @@ -1618,6 +1618,8 @@ for (auto i = c.begin(), last = c.end(); i != last; ) { } return original_size - c.size(); ``` ++ +Note that the references passed to `pred` are non-const. === Serialization diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 118300ca..83935fe8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -156,7 +156,9 @@ run unordered/serialization_tests.cpp gcc:space clang:on clang:space - /boost/serialization//boost_serialization/off ; + /boost/serialization//boost_serialization/off + /boost/container//boost_container/off + gcc,windows:no ; # Boost.Atomic no longer supports MinGW compile-fail unordered/insert_node_type_fail.cpp : UNORDERED_TEST_MAP : insert_node_type_fail_map ; compile-fail unordered/insert_node_type_fail.cpp : UNORDERED_TEST_MULTIMAP : insert_node_type_fail_multimap ; @@ -266,6 +268,8 @@ run unordered/serialization_tests.cpp clang:on clang:space /boost/serialization//boost_serialization/off + /boost/container//boost_container/off + gcc,windows:no # Boost.Atomic no longer supports MinGW : foa_serialization_tests ; local FOA_EXCEPTION_TESTS = @@ -402,6 +406,10 @@ run cfoa/serialization_tests.cpp clang:on clang:space /boost/serialization//boost_serialization/off + /boost/container//boost_container/off + gcc,windows:no # Boost.Atomic no longer supports MinGW + gcc,norecover:no # TSAN does not support atomic_thread_fence + clang,norecover:no # idem : cfoa_serialization_tests ; rule make_cfoa_interprocess_concurrency_tests ( name : defines ? ) diff --git a/test/unordered/erase_if.cpp b/test/unordered/erase_if.cpp index 5a10ace4..c5ba47d0 100644 --- a/test/unordered/erase_if.cpp +++ b/test/unordered/erase_if.cpp @@ -1,4 +1,5 @@ // Copyright 2021-2022 Christian Mazakas. +// Copyright 2025 Joaquin M Lopez Munoz. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -42,8 +43,35 @@ namespace test { } }; + template + struct non_const_pred; + + template + struct non_const_pred > + { + bool operator()(std::pair& x) const + { + U u = std::move(x.second); + (void)u; + return true; + } + }; + } // namespace test +template void test_map_nonconst_erase_if() +{ + typedef UnorderedMap map_type; + typedef typename map_type::value_type value_type; + typedef typename map_type::size_type size_type; + + map_type m; + m.insert(value_type()); + size_type num_erased = erase_if(m, test::non_const_pred()); + BOOST_TEST(m.empty()); + BOOST_TEST_EQ(num_erased, 1u); +} + template void test_map_erase_if() { typedef UnorderedMap map_type; @@ -71,6 +99,8 @@ template void test_map_erase_if() num_erased = erase_if(map, test::is_even()); BOOST_TEST_EQ(map.size(), 2u); BOOST_TEST_EQ(num_erased, size - map.size()); + + test_map_nonconst_erase_if(); } template void test_set_erase_if()