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.
This commit is contained in:
parent
48e4a9d938
commit
f54ceb2062
17 changed files with 121 additions and 21 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue