-
Notifications
You must be signed in to change notification settings - Fork 141
Description
I've stumbled upon a bug in my robin_hood map which also uses backward shift deleting, and wondered how you solve this issue in tsl::robin_map, and it seems you have exactly the same issue. (see martinus/robin-hood-hashing#42)
The problem is that due to backward shift deleting, when iterating a map and erasing elements, it is possible that the same elements will be iterated over twice.
Here is a reproducer, where I insert two elements into the map. When erasing the second element, the first element will wrap around and be iterated over a second time. I currently think it is best to just claim that's the way it is, because I am afraid there is no easy workaround (except not using backward shift deleting)
template <typename T>
struct BadHash {
size_t operator()(T const& val) const {
return static_cast<size_t>(val);
}
};
int main(int, char**) {
tsl::robin_map<int, int, BadHash<int>> map;
map.reserve(16); // resizes with mask 31
map.emplace(31, 1); // gets into last bucket
map.emplace(1024 + 31, 2); // would also get into last bucket, but wraps around
// first entry in the map
auto it = map.begin();
std::cout << it->first << "->" << it->second << std::endl;
// second entry in the map, erase it
++it;
std::cout << it->first << "->" << it->second << std::endl;
it = map.erase(it);
// now all two elements are iterated, we should be at the map's end, but due to backward shift
// deletion we are not
if (it != map.end()) {
std::cout << it->first << "->" << it->second << std::endl;
}
it = map.erase(it);
std::cout << "are we now at the end? " << (it == map.end()) << std::endl;
}I wonder what you think about that issue?