Add erase_if custom API - issue #84

This commit is contained in:
greg
2021-03-15 11:20:49 -04:00
parent 8335afbbb6
commit 08c10a02d5
2 changed files with 39 additions and 0 deletions
+29
View File
@@ -3622,6 +3622,17 @@ public:
return modify_if_impl<K, F, typename Lockable::UniqueLock>(key, std::forward<F>(f));
}
// if map contains key, lambda is called with the mapped value (under write lock protection).
// If the lambda returns true, the key is subsequently erased from the map (the write lock
// is only released after erase).
// returns true if key was erased, false otherwise.
// ----------------------------------------------------------------------------------------------------
template <class K = key_type, class F>
bool erase_if(const key_arg<K>& key, F&& f) {
return erase_if_impl<K, F, typename Lockable::UniqueLock>(key, std::forward<F>(f));
}
// if map does not contains key, it is inserted and the mapped value is value-constructed
// with the provided arguments (if any), as with try_emplace.
// if map already contains key, then the lambda is called with the mapped value (under
@@ -3670,6 +3681,24 @@ private:
return true;
}
template <class K = key_type, class F, class L>
bool erase_if_impl(const key_arg<K>& key, F&& f) {
#if __cplusplus >= 201703L
static_assert(std::is_invocable<F, mapped_type&>::value);
#endif
L m;
auto it = this->template find<K, L>(key, this->hash(key), m);
if (it == this->end())
return false;
if (std::forward<F>(f)(Policy::value(&*it)))
{
this->erase(it);
return true;
}
return false;
}
template <class K, class V>
std::pair<iterator, bool> insert_or_assign_impl(K&& k, V&& v) {
typename Lockable::UniqueLock m;
+10
View File
@@ -59,6 +59,16 @@ TEST(THIS_TEST_NAME, ThreadSafeContains) {
[](int& v) { v = 6; }, // called only when key was already present
[](const Map::constructor& ctor) { ctor(5, 13); }); // construct value_type in place when key not present
EXPECT_EQ(m[5], 6);
// test erase_if
// -------------
EXPECT_EQ(m.erase_if(4, [](int& v) { assert(0); return v==12; }), false); // m[4] not present - lambda not called
EXPECT_EQ(m.erase_if(5, [](int& v) { return v==12; }), false); // m[5] == 6, so erase not performed
EXPECT_EQ(m[5], 6);
EXPECT_EQ(m.erase_if(5, [](int& v) { return v==6; }), true); // lambda returns true, so m[5] erased
EXPECT_EQ(m[5], 0);
}
} // namespace