mirror of
https://github.com/boostorg/unordered.git
synced 2025-08-01 12:24:27 +02:00
Merge pull request #105 from cmazakas/feature/erase_if
Implement `erase_if`
This commit is contained in:
@@ -11,7 +11,8 @@
|
|||||||
* Improved {cpp}20 support:
|
* Improved {cpp}20 support:
|
||||||
** All containers have been updated to support
|
** All containers have been updated to support
|
||||||
heterogeneous `count`, `equal_range` and `find`.
|
heterogeneous `count`, `equal_range` and `find`.
|
||||||
** All containers now implement the member function `contains`
|
** All containers now implement the member function `contains`.
|
||||||
|
** `erase_if` has been implemented for all containers.
|
||||||
* Improved {cpp}23 support:
|
* Improved {cpp}23 support:
|
||||||
** All containers have been updated to support
|
** All containers have been updated to support
|
||||||
heterogeneous `erase` and `extract`.
|
heterogeneous `erase` and `extract`.
|
||||||
|
@@ -198,6 +198,10 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
|
|||||||
void xref:#unordered_map_swap_2[swap](unordered_map<Key, T, Hash, Pred, Alloc>& x,
|
void xref:#unordered_map_swap_2[swap](unordered_map<Key, T, Hash, Pred, Alloc>& x,
|
||||||
unordered_map<Key, T, Hash, Pred, Alloc>& y)
|
unordered_map<Key, T, Hash, Pred, Alloc>& y)
|
||||||
noexcept(noexcept(x.swap(y)));
|
noexcept(noexcept(x.swap(y)));
|
||||||
|
|
||||||
|
template<class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_map<K, T, H, P, A>::size_type
|
||||||
|
xref:#unordered_map_erase_if[erase_if](unordered_map<K, T, H, P, A>& c, Predicate pred);
|
||||||
-----
|
-----
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1424,4 +1428,31 @@ Effects:;; `x.swap(y)`
|
|||||||
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
||||||
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
=== erase_if
|
||||||
|
```c++
|
||||||
|
template<class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_map<K, T, H, P, A>::size_type
|
||||||
|
erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);
|
||||||
|
```
|
||||||
|
|
||||||
|
Traverses the container `c` and removes all elements for which the supplied predicate returns `true`.
|
||||||
|
|
||||||
|
[horizontal]
|
||||||
|
Returns:;; The number of erased elements.
|
||||||
|
Notes:;; Equivalent to: +
|
||||||
|
+
|
||||||
|
```c++
|
||||||
|
auto original_size = c.size();
|
||||||
|
for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||||
|
if (pred(*i)) {
|
||||||
|
i = c.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_size - c.size();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
@@ -193,6 +193,11 @@ template<class Key, class T, class Hash, class Pred, class Alloc>
|
|||||||
void xref:#unordered_multimap_swap_2[swap](unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
|
void xref:#unordered_multimap_swap_2[swap](unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
|
||||||
unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
|
unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
|
||||||
noexcept(noexcept(x.swap(y)));
|
noexcept(noexcept(x.swap(y)));
|
||||||
|
|
||||||
|
template<class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multimap<K, T, H, P, A>::size_type
|
||||||
|
xref:#unordered_multimap_erase_if[erase_if](unordered_multimap<K, T, H, P, A>& c, Predicate pred);
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1368,4 +1373,31 @@ Effects:;; `x.swap(y)`
|
|||||||
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
||||||
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
=== erase_if
|
||||||
|
```c++
|
||||||
|
template<class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multimap<K, T, H, P, A>::size_type
|
||||||
|
erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);
|
||||||
|
```
|
||||||
|
|
||||||
|
Traverses the container `c` and removes all elements for which the supplied predicate returns `true`.
|
||||||
|
|
||||||
|
[horizontal]
|
||||||
|
Returns:;; The number of erased elements.
|
||||||
|
Notes:;; Equivalent to: +
|
||||||
|
+
|
||||||
|
```c++
|
||||||
|
auto original_size = c.size();
|
||||||
|
for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||||
|
if (pred(*i)) {
|
||||||
|
i = c.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_size - c.size();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
@@ -187,6 +187,10 @@ template<class Key, class Hash, class Pred, class Alloc>
|
|||||||
void xref:#unordered_multiset_swap_2[swap](unordered_multiset<Key, Hash, Pred, Alloc>& x,
|
void xref:#unordered_multiset_swap_2[swap](unordered_multiset<Key, Hash, Pred, Alloc>& x,
|
||||||
unordered_multiset<Key, Hash, Pred, Alloc>& y)
|
unordered_multiset<Key, Hash, Pred, Alloc>& y)
|
||||||
noexcept(noexcept(x.swap(y)));
|
noexcept(noexcept(x.swap(y)));
|
||||||
|
|
||||||
|
template<class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multiset<K, H, P, A>::size_type
|
||||||
|
xref:#unordered_multiset_erase_if[erase_if](unordered_multiset<K, H, P, A>& c, Predicate pred);
|
||||||
-----
|
-----
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1326,4 +1330,31 @@ Effects:;; `x.swap(y)`
|
|||||||
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor or copy assignment operator of `key_equal` or `hasher`.
|
||||||
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
=== erase_if
|
||||||
|
```c++
|
||||||
|
template<class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multiset<K, H, P, A>::size_type
|
||||||
|
erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);
|
||||||
|
```
|
||||||
|
|
||||||
|
Traverses the container `c` and removes all elements for which the supplied predicate returns `true`.
|
||||||
|
|
||||||
|
[horizontal]
|
||||||
|
Returns:;; The number of erased elements.
|
||||||
|
Notes:;; Equivalent to: +
|
||||||
|
+
|
||||||
|
```c++
|
||||||
|
auto original_size = c.size();
|
||||||
|
for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||||
|
if (pred(*i)) {
|
||||||
|
i = c.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_size - c.size();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
@@ -188,6 +188,10 @@ template<class Key, class Hash, class Pred, class Alloc>
|
|||||||
void xref:#unordered_set_swap_2[swap](unordered_set<Key, Hash, Pred, Alloc>& x,
|
void xref:#unordered_set_swap_2[swap](unordered_set<Key, Hash, Pred, Alloc>& x,
|
||||||
unordered_set<Key, Hash, Pred, Alloc>& y)
|
unordered_set<Key, Hash, Pred, Alloc>& y)
|
||||||
noexcept(noexcept(x.swap(y)));
|
noexcept(noexcept(x.swap(y)));
|
||||||
|
|
||||||
|
template<class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_set<K, H, P, A>::size_type
|
||||||
|
xref:#unordered_set_erase_if[erase_if](unordered_set<K, H, P, A>& c, Predicate pred);
|
||||||
-----
|
-----
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1349,3 +1353,30 @@ Throws:;; Doesn't throw an exception unless it is thrown by the copy constructor
|
|||||||
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
Notes:;; The exception specifications aren't quite the same as the C++11 standard, as the equality predicate and hash function are swapped using their copy constructors.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
=== erase_if
|
||||||
|
```c++
|
||||||
|
template<class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_set<K, H, P, A>::size_type
|
||||||
|
erase_if(unordered_set<K, H, P, A>& c, Predicate pred);
|
||||||
|
```
|
||||||
|
|
||||||
|
Traverses the container `c` and removes all elements for which the supplied predicate returns `true`.
|
||||||
|
|
||||||
|
[horizontal]
|
||||||
|
Returns:;; The number of erased elements.
|
||||||
|
Notes:;; Equivalent to: +
|
||||||
|
+
|
||||||
|
```c++
|
||||||
|
auto original_size = c.size();
|
||||||
|
for (auto i = c.begin(), last = c.end(); i != last; ) {
|
||||||
|
if (pred(*i)) {
|
||||||
|
i = c.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_size - c.size();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
@@ -4360,6 +4360,25 @@ namespace boost {
|
|||||||
typedef typename pick::bucket bucket;
|
typedef typename pick::bucket bucket;
|
||||||
typedef typename pick::link_pointer link_pointer;
|
typedef typename pick::link_pointer link_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Container, class Predicate>
|
||||||
|
typename Container::size_type erase_if(Container& c, Predicate& pred)
|
||||||
|
{
|
||||||
|
typedef typename Container::size_type size_type;
|
||||||
|
typedef typename Container::iterator iterator;
|
||||||
|
|
||||||
|
size_type const size = c.size();
|
||||||
|
|
||||||
|
for (iterator pos = c.begin(), end = c.end(); pos != end;) {
|
||||||
|
if (pred(*pos)) {
|
||||||
|
pos = c.erase(pos);
|
||||||
|
} else {
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (size - c.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2168,6 +2168,13 @@ namespace boost {
|
|||||||
m1.swap(m2);
|
m1.swap(m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_map<K, T, H, P, A>::size_type erase_if(
|
||||||
|
unordered_map<K, T, H, P, A>& c, Predicate pred)
|
||||||
|
{
|
||||||
|
return detail::erase_if(c, pred);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <class K, class T, class H, class P, class A>
|
template <class K, class T, class H, class P, class A>
|
||||||
@@ -2613,6 +2620,13 @@ namespace boost {
|
|||||||
m1.swap(m2);
|
m1.swap(m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multimap<K, T, H, P, A>::size_type erase_if(
|
||||||
|
unordered_multimap<K, T, H, P, A>& c, Predicate pred)
|
||||||
|
{
|
||||||
|
return detail::erase_if(c, pred);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename N, class K, class T, class A> class node_handle_map
|
template <typename N, class K, class T, class A> class node_handle_map
|
||||||
{
|
{
|
||||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_map)
|
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_map)
|
||||||
|
@@ -34,6 +34,10 @@ namespace boost {
|
|||||||
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
|
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
|
||||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||||
|
|
||||||
|
template <class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_map<K, T, H, P, A>::size_type erase_if(
|
||||||
|
unordered_map<K, T, H, P, A>& c, Predicate pred);
|
||||||
|
|
||||||
template <class K, class T, class H = boost::hash<K>,
|
template <class K, class T, class H = boost::hash<K>,
|
||||||
class P = std::equal_to<K>,
|
class P = std::equal_to<K>,
|
||||||
class A = std::allocator<std::pair<const K, T> > >
|
class A = std::allocator<std::pair<const K, T> > >
|
||||||
@@ -50,6 +54,10 @@ namespace boost {
|
|||||||
unordered_multimap<K, T, H, P, A>& m2)
|
unordered_multimap<K, T, H, P, A>& m2)
|
||||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||||
|
|
||||||
|
template <class K, class T, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multimap<K, T, H, P, A>::size_type erase_if(
|
||||||
|
unordered_multimap<K, T, H, P, A>& c, Predicate pred);
|
||||||
|
|
||||||
template <class N, class K, class T, class A> class node_handle_map;
|
template <class N, class K, class T, class A> class node_handle_map;
|
||||||
template <class N, class K, class T, class A> struct insert_return_type_map;
|
template <class N, class K, class T, class A> struct insert_return_type_map;
|
||||||
}
|
}
|
||||||
|
@@ -1676,6 +1676,13 @@ namespace boost {
|
|||||||
m1.swap(m2);
|
m1.swap(m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_set<K, H, P, A>::size_type erase_if(
|
||||||
|
unordered_set<K, H, P, A>& c, Predicate pred)
|
||||||
|
{
|
||||||
|
return detail::erase_if(c, pred);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <class T, class H, class P, class A>
|
template <class T, class H, class P, class A>
|
||||||
@@ -2079,6 +2086,13 @@ namespace boost {
|
|||||||
m1.swap(m2);
|
m1.swap(m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multiset<K, H, P, A>::size_type erase_if(
|
||||||
|
unordered_multiset<K, H, P, A>& c, Predicate pred)
|
||||||
|
{
|
||||||
|
return detail::erase_if(c, pred);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename N, typename T, typename A> class node_handle_set
|
template <typename N, typename T, typename A> class node_handle_set
|
||||||
{
|
{
|
||||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
|
BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set)
|
||||||
|
@@ -33,6 +33,10 @@ namespace boost {
|
|||||||
unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
|
unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
|
||||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||||
|
|
||||||
|
template <class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_set<K, H, P, A>::size_type erase_if(
|
||||||
|
unordered_set<K, H, P, A>& c, Predicate pred);
|
||||||
|
|
||||||
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
|
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
|
||||||
class A = std::allocator<T> >
|
class A = std::allocator<T> >
|
||||||
class unordered_multiset;
|
class unordered_multiset;
|
||||||
@@ -48,6 +52,10 @@ namespace boost {
|
|||||||
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
|
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
|
||||||
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
|
||||||
|
|
||||||
|
template <class K, class H, class P, class A, class Predicate>
|
||||||
|
typename unordered_multiset<K, H, P, A>::size_type erase_if(
|
||||||
|
unordered_multiset<K, H, P, A>& c, Predicate pred);
|
||||||
|
|
||||||
template <class N, class T, class A> class node_handle_set;
|
template <class N, class T, class A> class node_handle_set;
|
||||||
template <class N, class T, class A> struct insert_return_type_set;
|
template <class N, class T, class A> struct insert_return_type_set;
|
||||||
}
|
}
|
||||||
|
@@ -76,6 +76,7 @@ test-suite unordered
|
|||||||
[ run unordered/reserve_tests.cpp ]
|
[ run unordered/reserve_tests.cpp ]
|
||||||
[ run unordered/contains_tests.cpp ]
|
[ run unordered/contains_tests.cpp ]
|
||||||
[ run unordered/mix_policy.cpp ]
|
[ run unordered/mix_policy.cpp ]
|
||||||
|
[ run unordered/erase_if.cpp ]
|
||||||
|
|
||||||
[ run unordered/compile_set.cpp : :
|
[ run unordered/compile_set.cpp : :
|
||||||
: <define>BOOST_UNORDERED_USE_MOVE
|
: <define>BOOST_UNORDERED_USE_MOVE
|
||||||
|
168
test/unordered/erase_if.cpp
Normal file
168
test/unordered/erase_if.cpp
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
// Copyright 2021 Christian Mazakas.
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#include "../helpers/prefix.hpp"
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include "../helpers/postfix.hpp"
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#include "../helpers/test.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#if BOOST_CXX_VERSION >= 201103L
|
||||||
|
#define UNORDERED_LVALUE_QUAL &
|
||||||
|
#else
|
||||||
|
#define UNORDERED_LVALUE_QUAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace test {
|
||||||
|
struct is_even
|
||||||
|
{
|
||||||
|
is_even() {}
|
||||||
|
|
||||||
|
#if BOOST_CXX_VERSION >= 201703L
|
||||||
|
// immovable for C++17
|
||||||
|
is_even(is_even const&) = delete;
|
||||||
|
is_even(is_even&&) = delete;
|
||||||
|
|
||||||
|
is_even& operator=(is_even const&) = delete;
|
||||||
|
is_even& operator=(is_even&&) = delete;
|
||||||
|
#elif BOOST_CXX_VERSION >= 201103L
|
||||||
|
// move-only for C++11
|
||||||
|
is_even(is_even const&) = delete;
|
||||||
|
is_even(is_even&&) = default;
|
||||||
|
|
||||||
|
is_even& operator=(is_even const&) = delete;
|
||||||
|
is_even& operator=(is_even&&) = default;
|
||||||
|
#else
|
||||||
|
// copyable otherwise
|
||||||
|
is_even(is_even const&) {}
|
||||||
|
is_even& operator=(is_even const&) { return *this; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool operator()(
|
||||||
|
std::pair<std::string const, int>& key_value) UNORDERED_LVALUE_QUAL
|
||||||
|
{
|
||||||
|
int const v = key_value.second;
|
||||||
|
return (v % 2 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(int const& value) UNORDERED_LVALUE_QUAL
|
||||||
|
{
|
||||||
|
int const v = value;
|
||||||
|
return (v % 2 == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct is_too_large
|
||||||
|
{
|
||||||
|
is_too_large() {}
|
||||||
|
|
||||||
|
#if BOOST_CXX_VERSION >= 201703L
|
||||||
|
// immovable for C++17
|
||||||
|
is_too_large(is_too_large const&) = delete;
|
||||||
|
is_too_large(is_too_large&&) = delete;
|
||||||
|
|
||||||
|
is_too_large& operator=(is_too_large const&) = delete;
|
||||||
|
is_too_large& operator=(is_too_large&&) = delete;
|
||||||
|
#elif BOOST_CXX_VERSION >= 201103L
|
||||||
|
// move-only for C++11
|
||||||
|
is_too_large(is_too_large const&) = delete;
|
||||||
|
is_too_large(is_too_large&&) = default;
|
||||||
|
|
||||||
|
is_too_large& operator=(is_too_large const&) = delete;
|
||||||
|
is_too_large& operator=(is_too_large&&) = default;
|
||||||
|
#else
|
||||||
|
// copyable otherwise
|
||||||
|
is_too_large(is_too_large const&) {}
|
||||||
|
|
||||||
|
is_too_large& operator=(is_too_large const&) { return *this; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool operator()(
|
||||||
|
std::pair<std::string const, int>& key_value) UNORDERED_LVALUE_QUAL
|
||||||
|
{
|
||||||
|
int const v = key_value.second;
|
||||||
|
return v >= 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(int const& value) UNORDERED_LVALUE_QUAL
|
||||||
|
{
|
||||||
|
int const v = value;
|
||||||
|
return v >= 1000;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace test
|
||||||
|
|
||||||
|
template <class UnorderedMap> void test_map_erase_if()
|
||||||
|
{
|
||||||
|
typedef UnorderedMap map_type;
|
||||||
|
typedef typename map_type::size_type size_type;
|
||||||
|
|
||||||
|
map_type map;
|
||||||
|
size_type num_erased = erase_if(map, test::is_even());
|
||||||
|
BOOST_TEST(map.empty());
|
||||||
|
BOOST_TEST_EQ(num_erased, 0u);
|
||||||
|
|
||||||
|
map.emplace("a", 1);
|
||||||
|
map.emplace("b", 2);
|
||||||
|
map.emplace("b", 4);
|
||||||
|
map.emplace("b", 8);
|
||||||
|
map.emplace("b", 16);
|
||||||
|
map.emplace("c", 3);
|
||||||
|
|
||||||
|
size_type size = map.size();
|
||||||
|
|
||||||
|
num_erased = erase_if(map, test::is_too_large());
|
||||||
|
|
||||||
|
BOOST_TEST_EQ(map.size(), size);
|
||||||
|
BOOST_TEST_EQ(num_erased, 0u);
|
||||||
|
|
||||||
|
num_erased = erase_if(map, test::is_even());
|
||||||
|
BOOST_TEST_EQ(map.size(), 2u);
|
||||||
|
BOOST_TEST_EQ(num_erased, size - map.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class UnorderedSet> void test_set_erase_if()
|
||||||
|
{
|
||||||
|
typedef UnorderedSet set_type;
|
||||||
|
typedef typename set_type::size_type size_type;
|
||||||
|
|
||||||
|
set_type set;
|
||||||
|
size_type num_erased = erase_if(set, test::is_even());
|
||||||
|
BOOST_TEST(set.empty());
|
||||||
|
BOOST_TEST_EQ(num_erased, 0u);
|
||||||
|
|
||||||
|
set.emplace(1);
|
||||||
|
set.emplace(2);
|
||||||
|
set.emplace(2);
|
||||||
|
set.emplace(2);
|
||||||
|
set.emplace(2);
|
||||||
|
set.emplace(3);
|
||||||
|
|
||||||
|
size_type size = set.size();
|
||||||
|
|
||||||
|
num_erased = erase_if(set, test::is_too_large());
|
||||||
|
|
||||||
|
BOOST_TEST_EQ(set.size(), size);
|
||||||
|
BOOST_TEST_EQ(num_erased, 0u);
|
||||||
|
|
||||||
|
num_erased = erase_if(set, test::is_even());
|
||||||
|
BOOST_TEST_EQ(set.size(), 2u);
|
||||||
|
BOOST_TEST_EQ(num_erased, size - set.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNORDERED_AUTO_TEST (unordered_erase_if) {
|
||||||
|
test_map_erase_if<boost::unordered_map<std::string, int> >();
|
||||||
|
test_map_erase_if<boost::unordered_multimap<std::string, int> >();
|
||||||
|
|
||||||
|
test_set_erase_if<boost::unordered_set<int> >();
|
||||||
|
test_set_erase_if<boost::unordered_multiset<int> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
RUN_TESTS()
|
Reference in New Issue
Block a user