Explicitly expose EraseIf in flat_map/flat_set

Before this CL, EraseIf was defined in flat_tree.h, but that file can
only be included by the flat_map/flat_set implementation, as it's an
internal file with limited visibility.

This CL will move the flat_tree's base EraseIf implementation to the
internal namespace and define specific variants of it in flat_map.h and
flat_set.h

Bug: webrtc:12689
Change-Id: Idf31915f4abe36ad302c1da669b702974a27c647
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/225206
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34431}
This commit is contained in:
Victor Boivie 2021-07-07 10:48:28 +02:00 committed by WebRTC LUCI CQ
parent 18649971ab
commit 5900ba0ee8
5 changed files with 66 additions and 3 deletions

View file

@ -359,6 +359,16 @@ void flat_map<Key, Mapped, Compare, Container>::swap(flat_map& other) noexcept {
tree::swap(other);
}
// Erases all elements that match predicate. It has O(size) complexity.
//
// flat_map<int, Timestamp> last_times;
// ...
// EraseIf(last_times,
// [&](const auto& element) { return now - element.second > kLimit; });
// NOLINTNEXTLINE(misc-unused-using-decls)
using ::webrtc::flat_containers_internal::EraseIf;
} // namespace webrtc
#endif // RTC_BASE_CONTAINERS_FLAT_MAP_H_

View file

@ -429,5 +429,26 @@ TEST(FlatMap, UsingTransparentCompare) {
m.erase(m.cbegin());
}
TEST(FlatMap, SupportsEraseIf) {
flat_map<MoveOnlyInt, MoveOnlyInt> m;
m.insert(std::make_pair(MoveOnlyInt(1), MoveOnlyInt(1)));
m.insert(std::make_pair(MoveOnlyInt(2), MoveOnlyInt(2)));
m.insert(std::make_pair(MoveOnlyInt(3), MoveOnlyInt(3)));
m.insert(std::make_pair(MoveOnlyInt(4), MoveOnlyInt(4)));
m.insert(std::make_pair(MoveOnlyInt(5), MoveOnlyInt(5)));
EraseIf(m, [to_be_removed = MoveOnlyInt(2)](
const std::pair<MoveOnlyInt, MoveOnlyInt>& e) {
return e.first == to_be_removed;
});
EXPECT_EQ(m.size(), 4u);
ASSERT_TRUE(m.find(MoveOnlyInt(1)) != m.end());
ASSERT_FALSE(m.find(MoveOnlyInt(2)) != m.end());
ASSERT_TRUE(m.find(MoveOnlyInt(3)) != m.end());
ASSERT_TRUE(m.find(MoveOnlyInt(4)) != m.end());
ASSERT_TRUE(m.find(MoveOnlyInt(5)) != m.end());
}
} // namespace
} // namespace webrtc

View file

@ -161,6 +161,18 @@ template <class Key,
using flat_set = typename ::webrtc::flat_containers_internal::
flat_tree<Key, webrtc::identity, Compare, Container>;
// ----------------------------------------------------------------------------
// General operations.
// Erases all elements that match predicate. It has O(size) complexity.
//
// flat_set<int> numbers;
// ...
// EraseIf(numbers, [](int number) { return number % 2 == 1; });
// NOLINTNEXTLINE(misc-unused-using-decls)
using ::webrtc::flat_containers_internal::EraseIf;
} // namespace webrtc
#endif // RTC_BASE_CONTAINERS_FLAT_SET_H_

View file

@ -125,5 +125,25 @@ TEST(FlatSet, UsingTransparentCompare) {
s.erase(s.begin());
s.erase(s.cbegin());
}
TEST(FlatSet, SupportsEraseIf) {
flat_set<MoveOnlyInt> s;
s.emplace(MoveOnlyInt(1));
s.emplace(MoveOnlyInt(2));
s.emplace(MoveOnlyInt(3));
s.emplace(MoveOnlyInt(4));
s.emplace(MoveOnlyInt(5));
EraseIf(s, [to_be_removed = MoveOnlyInt(2)](const MoveOnlyInt& elem) {
return elem == to_be_removed;
});
EXPECT_EQ(s.size(), 4u);
ASSERT_TRUE(s.find(MoveOnlyInt(1)) != s.end());
ASSERT_FALSE(s.find(MoveOnlyInt(2)) != s.end());
ASSERT_TRUE(s.find(MoveOnlyInt(3)) != s.end());
ASSERT_TRUE(s.find(MoveOnlyInt(4)) != s.end());
ASSERT_TRUE(s.find(MoveOnlyInt(5)) != s.end());
}
} // namespace
} // namespace webrtc

View file

@ -1076,8 +1076,6 @@ auto flat_tree<Key, GetKeyFromValue, KeyCompare, Container>::
return emplace_key_args(key, std::forward<Args>(args)...);
}
} // namespace flat_containers_internal
// ----------------------------------------------------------------------------
// Free functions.
@ -1091,12 +1089,14 @@ size_t EraseIf(
webrtc::flat_containers_internal::
flat_tree<Key, GetKeyFromValue, KeyCompare, Container>& container,
Predicate pred) {
auto it = std::remove_if(container.begin(), container.end(), pred);
auto it = std::remove_if(container.begin(), container.end(),
std::forward<Predicate>(pred));
size_t removed = std::distance(it, container.end());
container.erase(it, container.end());
return removed;
}
} // namespace flat_containers_internal
} // namespace webrtc
#endif // RTC_BASE_CONTAINERS_FLAT_TREE_H_