Skip to content

Commit

Permalink
Add robin_map/set::erase_it() method (fixes #75)
Browse files Browse the repository at this point in the history
This commit introduces a new method ``void erase_it(iterator)`` to both
set and map classes resembling the existing ``iterator
erase(iterator)``.

The main difference is that it does _not_ return an iterator, which is
useful to avoid a performance pitfall explained in issue #75.
  • Loading branch information
wjakob committed Apr 17, 2024
1 parent 048eb14 commit b30e0e7
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 4 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ int main() {
}
```

#### Element erasure

Besides the regular ``iterator erase(iterator)`` method also provided by STL
map and set types, ``robin_map`` and ``robin_set`` provide a ``void
erase_it(iterator)`` method that does _not_ return an iterator. Computing a
valid iterator following element erasure comes at a computational cost that can
be avoided with this method when the return value is not needed.

#### Serialization

Expand Down
5 changes: 1 addition & 4 deletions include/tsl/robin_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
++pos;
}

m_try_shrink_on_next_insert = true;

return pos;
}

Expand Down Expand Up @@ -916,8 +914,6 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
auto it = find(key, hash);
if (it != end()) {
erase_from_bucket(it);
m_try_shrink_on_next_insert = true;

return 1;
} else {
return 0;
Expand Down Expand Up @@ -1211,6 +1207,7 @@ class robin_hash : private Hash, private KeyEqual, private GrowthPolicy {
previous_ibucket = ibucket;
ibucket = next_bucket(ibucket);
}
m_try_shrink_on_next_insert = true;
}

template <class K, class... Args>
Expand Down
2 changes: 2 additions & 0 deletions include/tsl/robin_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ class robin_map {
}
size_type erase(const key_type& key) { return m_ht.erase(key); }

void erase_it(iterator pos) { return m_ht.erase_from_bucket(pos); }

/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The
* hash value should be the same as hash_function()(key). Useful to speed-up
Expand Down
2 changes: 2 additions & 0 deletions include/tsl/robin_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ class robin_set {
}
size_type erase(const key_type& key) { return m_ht.erase(key); }

void erase_it(iterator pos) { return m_ht.erase_from_bucket(pos); }

/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The
* hash value should be the same as hash_function()(key). Useful to speed-up
Expand Down
11 changes: 11 additions & 0 deletions tests/robin_map_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,4 +1448,15 @@ BOOST_AUTO_TEST_CASE(test_precalculated_hash) {
BOOST_CHECK_EQUAL(map.erase(4, map.hash_function()(2)), 0);
}

BOOST_AUTO_TEST_CASE(test_erase_it) {
using Map = tsl::robin_map<int, int>;
Map map;
map.emplace(4, 5);
auto it = map.find(4);
BOOST_CHECK(it != map.end());
map.erase(it);
BOOST_CHECK(map.size() == 0);
}


BOOST_AUTO_TEST_SUITE_END()
10 changes: 10 additions & 0 deletions tests/robin_set_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,14 @@ BOOST_AUTO_TEST_CASE(test_serialize_deserialize) {
BOOST_CHECK(set_deserialized == set);
}

BOOST_AUTO_TEST_CASE(test_erase_it) {
using Set = tsl::robin_set<int>;
Set set;
set.emplace(4);
auto it = set.find(4);
BOOST_CHECK(it != set.end());
set.erase(it);
BOOST_CHECK(set.size() == 0);
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit b30e0e7

Please sign in to comment.