diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fd9d58..bce2ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,9 @@ if (PHMAP_BUILD_TESTS) phmap_cc_test(NAME dump_load SRCS "tests/dump_load_test.cc" COPTS "-DUNORDERED_MAP_CXX17" DEPS gmock_main) + phmap_cc_test(NAME erase_if SRCS "tests/erase_if_test.cc" + COPTS "-DUNORDERED_MAP_CXX17" DEPS gmock_main) + ## --------------- btree ----------------------------------------------- phmap_cc_test(NAME btree SRCS "tests/btree_test.cc" CLOPTS "-w" DEPS gmock_main) diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index f5db1cb..6ba25bc 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -4939,6 +4939,70 @@ public: } // namespace phmap + +namespace phmap { + namespace priv { + template + std::size_t erase_if(C &c, Pred pred) { + auto old_size = c.size(); + for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } + } + return old_size - c.size(); + } + } // priv +} // phmap + +namespace std { + + // ======== erase_if for phmap set containers ================================== + template + std::size_t erase_if(phmap::flat_hash_set& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::node_hash_set& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::parallel_flat_hash_set& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::parallel_node_hash_set& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + // ======== erase_if for phmap map containers ================================== + template + std::size_t erase_if(phmap::flat_hash_map& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::node_hash_map& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::parallel_flat_hash_map& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + + template + std::size_t erase_if(phmap::parallel_node_hash_map& c, Pred pred) { + return phmap::priv::erase_if(c, std::move(pred)); + } + +} // std + #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/tests/dump_load_test.cc b/tests/dump_load_test.cc index 94f83b1..b828eba 100644 --- a/tests/dump_load_test.cc +++ b/tests/dump_load_test.cc @@ -8,7 +8,7 @@ namespace phmap { namespace priv { namespace { -TEST(DumpLoad, FlatHashSet_uin32) { +TEST(DumpLoad, FlatHashSet_uint32) { phmap::flat_hash_set st1 = { 1991, 1202 }; { diff --git a/tests/erase_if_test.cc b/tests/erase_if_test.cc new file mode 100644 index 0000000..475276d --- /dev/null +++ b/tests/erase_if_test.cc @@ -0,0 +1,52 @@ +#include + +#include "gtest/gtest.h" + +#include "parallel_hashmap/phmap.h" + +namespace phmap { +namespace priv { +namespace { + +TEST(EraseIf, FlatHashSet_uint32) { + phmap::flat_hash_set st1 = { 3, 6, 7, 9 }; + auto num_erased = std::erase_if(st1, [](const uint32_t& v) { return v >= 7; }); + EXPECT_TRUE(num_erased == 2); + + phmap::flat_hash_set st2 = { 0, 2, 3, 6 }; + num_erased = std::erase_if(st2, [](const uint32_t& v) { return v <= 2; }); + EXPECT_TRUE(num_erased == 2); + + EXPECT_TRUE(st1 == st2); +} + +TEST(EraseIf, FlatHashMap_uint64_uint32) { + using map = phmap::flat_hash_map; + map st1 = { {3, 0}, {6, 0}, {7, 0}, {9, 0} }; + auto num_erased = std::erase_if(st1, [](const map::value_type& v) { return v.first >= 7; }); + EXPECT_TRUE(num_erased == 2); + + map st2 = { {0, 0}, {2, 0}, {3, 0}, {6, 0} }; + num_erased = std::erase_if(st2, [](const map::value_type& v) { return v.first <= 2; }); + EXPECT_TRUE(num_erased == 2); + + EXPECT_TRUE(st1 == st2); +} + +TEST(EraseIf, ParallelFlatHashMap_uint64_uint32) { + using map = phmap::parallel_flat_hash_map; + map st1 = { {3, 0}, {6, 0}, {7, 0}, {9, 0} }; + auto num_erased = std::erase_if(st1, [](const map::value_type& v) { return v.first >= 7; }); + EXPECT_TRUE(num_erased == 2); + + map st2 = { {0, 0}, {2, 0}, {3, 0}, {6, 0} }; + num_erased = std::erase_if(st2, [](const map::value_type& v) { return v.first <= 2; }); + EXPECT_TRUE(num_erased == 2); + + EXPECT_TRUE(st1 == st2); +} + +} +} +} +