I was wondering about uniqueness of a key object inside an std::unordered_multimap
when dealing with iteration.
I'll try to explain the point: I need to associate some data with the key type in the map, this data should not be considered in Hash
or KeyEqual
elements, but I need it to avoid storing a separate map with it (for optimization purposes).
So the code associated with my idea is the following:
struct Key {
void* data;
mutable bool attribute;
Key(void* data) : data(data), attribute(false) { }
bool operator==(const Key& other) const {
return data == other.data;
}
};
struct KeyHash {
size_t operator()(const Key& key) const {
return std::hash<void*>()(key.data);
}
};
class Foo {
public:
int i;
Foo(int i) : i(i) { }
};
std::unordered_multimap<Key, Foo, KeyHash> map;
The problem arises from the fact that although this works fine, there are no guarantees about the fact that the key retrieved as the first element of the std::pair<const Key, Foo>
mapping to a single element is always the same. Being a pair
of const Key
it sounds like that every element in the map has its copy of the key by value, so that if I do
void* target = new int();
map.emplace(std::make_pair(target, Foo(1)));
map.emplace(std::make_pair(target, Foo(2)));
auto pit = map.equal_range(target);
pit.first->first.attribute = true;
std::cout << std::boolalpha << (++pit.first)->first.attribute << endl;
This yields false
which is confirming what I was thinking. So there is indeed a lot of space wasted to store keys if you have multiple values with the same key (which is what you want since you are using an std::unordered_map
).
I don't see any other solution rather than something like
struct Value
{
std::vector<Foo> foos;
bool attribute;
};
std::unordered_map<void*, Value> map;
Which allows me to pair the attribute with the key but makes everything less clean since it requires working with two levels of iterators.
Are there other solutions I'm not seeing?
boost::multiindex
– Mayemap[target] = Foo(1);
std::unordered_multimap
doesn't overloadoperator[]
– Havocstd::unordered_map<Key, std::vector<Foo>>
, by any chance? That would happily associate multiple values with the same key, without duplicating the key. – Havocstd::unordered_map<Key, std::vector<Foo>>
? Same key would be stored just once. Only that your insert operation first needs to get a reference to that vector and append to it. – Obeisance