diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2022-11-24 21:09:03 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2022-11-25 15:06:25 +0000 |
commit | f54ceb2062c7fef294f85ae093914fa6c7ca35b8 (patch) | |
tree | 8e935211c279fc7accbe99a5d6fdcc23d59f065d | |
parent | 48e4a9d93885b3d82cfcbf1e804fe9c3eaabf157 (diff) | |
download | gcc-f54ceb2062c7fef294f85ae093914fa6c7ca35b8.zip gcc-f54ceb2062c7fef294f85ae093914fa6c7ca35b8.tar.gz gcc-f54ceb2062c7fef294f85ae093914fa6c7ca35b8.tar.bz2 |
libstdc++: Call predicate with non-const values in std::erase_if [PR107850]
As specified in the standard, the predicate for std::erase_if has to be
invocable as non-const with a non-const lvalues argument. Restore
support for predicates that only accept non-const arguments.
It's not strictly nevessary to change it for the set and unordered_set
overloads, because they only give const access to the elements anyway.
I've done it for them too just to keep them all consistent.
libstdc++-v3/ChangeLog:
PR libstdc++/107850
* include/bits/erase_if.h (__erase_nodes_if): Use non-const
reference to the container.
* include/experimental/map (erase_if): Likewise.
* include/experimental/set (erase_if): Likewise.
* include/experimental/unordered_map (erase_if): Likewise.
* include/experimental/unordered_set (erase_if): Likewise.
* include/std/map (erase_if): Likewise.
* include/std/set (erase_if): Likewise.
* include/std/unordered_map (erase_if): Likewise.
* include/std/unordered_set (erase_if): Likewise.
* testsuite/23_containers/map/erasure.cc: Check with
const-incorrect predicate.
* testsuite/23_containers/set/erasure.cc: Likewise.
* testsuite/23_containers/unordered_map/erasure.cc: Likewise.
* testsuite/23_containers/unordered_set/erasure.cc: Likewise.
* testsuite/experimental/map/erasure.cc: Likewise.
* testsuite/experimental/set/erasure.cc: Likewise.
* testsuite/experimental/unordered_map/erasure.cc: Likewise.
* testsuite/experimental/unordered_set/erasure.cc: Likewise.
-rw-r--r-- | libstdc++-v3/include/bits/erase_if.h | 2 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/map | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/set | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/unordered_map | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/experimental/unordered_set | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/map | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/set | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/unordered_map | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/unordered_set | 4 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/map/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/set/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/map/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/set/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc | 13 |
17 files changed, 121 insertions, 21 deletions
diff --git a/libstdc++-v3/include/bits/erase_if.h b/libstdc++-v3/include/bits/erase_if.h index 397207f..b336e26 100644 --- a/libstdc++-v3/include/bits/erase_if.h +++ b/libstdc++-v3/include/bits/erase_if.h @@ -49,7 +49,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Container, typename _UnsafeContainer, typename _Predicate> typename _Container::size_type - __erase_nodes_if(_Container& __cont, const _UnsafeContainer& __ucont, + __erase_nodes_if(_Container& __cont, _UnsafeContainer& __ucont, _Predicate __pred) { typename _Container::size_type __num = 0; diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map index 525252b..9557a2a 100644 --- a/libstdc++-v3/include/experimental/map +++ b/libstdc++-v3/include/experimental/map @@ -53,8 +53,7 @@ inline namespace fundamentals_v2 inline void erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& - __ucont = __cont; + _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -63,8 +62,7 @@ inline namespace fundamentals_v2 inline void erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& - __ucont = __cont; + _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set index b42a3cd..7d142e0 100644 --- a/libstdc++-v3/include/experimental/set +++ b/libstdc++-v3/include/experimental/set @@ -53,7 +53,7 @@ inline namespace fundamentals_v2 inline void erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont; + _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -62,7 +62,7 @@ inline namespace fundamentals_v2 inline void erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont; + _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map index ce56c2a..02bba7e 100644 --- a/libstdc++-v3/include/experimental/unordered_map +++ b/libstdc++-v3/include/experimental/unordered_map @@ -54,7 +54,7 @@ inline namespace fundamentals_v2 erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -65,7 +65,7 @@ inline namespace fundamentals_v2 erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set index c707587..04bbb7f 100644 --- a/libstdc++-v3/include/experimental/unordered_set +++ b/libstdc++-v3/include/experimental/unordered_set @@ -54,7 +54,7 @@ inline namespace fundamentals_v2 erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -65,7 +65,7 @@ inline namespace fundamentals_v2 erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __ucont = __cont; std::__detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map index c973a8e..9bf484d 100644 --- a/libstdc++-v3/include/std/map +++ b/libstdc++-v3/include/std/map @@ -98,8 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& - __ucont = __cont; + _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -108,8 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& - __ucont = __cont; + _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set index 4cbcba1..3ada45c 100644 --- a/libstdc++-v3/include/std/set +++ b/libstdc++-v3/include/std/set @@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename set<_Key, _Compare, _Alloc>::size_type erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont; + _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -103,7 +103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename multiset<_Key, _Compare, _Alloc>::size_type erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont; + _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map index 323edcd..38c4987 100644 --- a/libstdc++-v3/include/std/unordered_map +++ b/libstdc++-v3/include/std/unordered_map @@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -90,7 +90,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set index 998417f..09f74ab 100644 --- a/libstdc++-v3/include/std/unordered_set +++ b/libstdc++-v3/include/std/unordered_set @@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } @@ -89,7 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont, _Predicate __pred) { - const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& + _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __ucont = __cont; return __detail::__erase_nodes_if(__cont, __ucont, __pred); } diff --git a/libstdc++-v3/testsuite/23_containers/map/erasure.cc b/libstdc++-v3/testsuite/23_containers/map/erasure.cc index badf789..643ad0a 100644 --- a/libstdc++-v3/testsuite/23_containers/map/erasure.cc +++ b/libstdc++-v3/testsuite/23_containers/map/erasure.cc @@ -61,11 +61,24 @@ test02() VERIFY( num == 4 ); } +void +test_pr107850() +{ + // Predicate only callable as non-const and only accepts non-const argument. + struct Pred { bool operator()(std::pair<const int, int>&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::map<int, int> m; + std::erase_if(m, pred); + std::multimap<int, int> mm; + std::erase_if(mm, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/set/erasure.cc b/libstdc++-v3/testsuite/23_containers/set/erasure.cc index fe0c4b8..bfa28f2 100644 --- a/libstdc++-v3/testsuite/23_containers/set/erasure.cc +++ b/libstdc++-v3/testsuite/23_containers/set/erasure.cc @@ -49,11 +49,24 @@ test02() VERIFY( num == 4 ); } +void +test_pr107850() +{ + // Predicate only callable as non-const. + struct Pred { bool operator()(const int&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::set<int> s; + std::erase_if(s, pred); + std::multiset<int> ms; + std::erase_if(ms, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc index e6018186..8392e53 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc @@ -61,11 +61,24 @@ test02() VERIFY( num == 4 ); } +void +test_pr107850() +{ + // Predicate only callable as non-const and only accepts non-const argument. + struct Pred { bool operator()(std::pair<const int, int>&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_map<int, int> m; + std::erase_if(m, pred); + std::unordered_multimap<int, int> mm; + std::erase_if(mm, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc index 4cb8041..7684549 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc @@ -51,11 +51,24 @@ test02() VERIFY( num == 4 ); } +void +test_pr107850() +{ + // Predicate only callable as non-const. + struct Pred { bool operator()(const int&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_set<int> s; + std::erase_if(s, pred); + std::unordered_multiset<int> ms; + std::erase_if(ms, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/experimental/map/erasure.cc b/libstdc++-v3/testsuite/experimental/map/erasure.cc index 8470ab2..b377926 100644 --- a/libstdc++-v3/testsuite/experimental/map/erasure.cc +++ b/libstdc++-v3/testsuite/experimental/map/erasure.cc @@ -52,11 +52,24 @@ test02() VERIFY( mm == t ); } +void +test_pr107850() +{ + // Predicate only callable as non-const and only accepts non-const argument. + struct Pred { bool operator()(std::pair<const int, int>&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::map<int, int> m; + std::experimental::erase_if(m, pred); + std::multimap<int, int> mm; + std::experimental::erase_if(mm, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/experimental/set/erasure.cc b/libstdc++-v3/testsuite/experimental/set/erasure.cc index 1e04c34..b427228 100644 --- a/libstdc++-v3/testsuite/experimental/set/erasure.cc +++ b/libstdc++-v3/testsuite/experimental/set/erasure.cc @@ -40,11 +40,24 @@ test02() VERIFY( ms == t ); } +void +test_pr107850() +{ + // Predicate only callable as non-const. + struct Pred { bool operator()(const int&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::set<int> s; + std::experimental::erase_if(s, pred); + std::multiset<int> ms; + std::experimental::erase_if(ms, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc b/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc index 022f575..cd281bc 100644 --- a/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc +++ b/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc @@ -52,11 +52,24 @@ test02() VERIFY( umm == t ); } +void +test_pr107850() +{ + // Predicate only callable as non-const and only accepts non-const argument. + struct Pred { bool operator()(std::pair<const int, int>&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_map<int, int> m; + std::experimental::erase_if(m, pred); + std::unordered_multimap<int, int> mm; + std::experimental::erase_if(mm, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } diff --git a/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc b/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc index d261812..918f455 100644 --- a/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc +++ b/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc @@ -42,11 +42,24 @@ test02() VERIFY( ums == t ); } +void +test_pr107850() +{ + // Predicate only callable as non-const. + struct Pred { bool operator()(const int&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_set<int> s; + std::experimental::erase_if(s, pred); + std::unordered_multiset<int> ms; + std::experimental::erase_if(ms, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; } |