Middle
What needs to be done to store your structure in an unordered_map?
sobes.tech AI
Answer from AI
To store a structure as a key in std::unordered_map, you need to provide:
- A hash function: Finds a hash value for an instance of the structure.
- An equality comparison operator (
operator==): Compares two instances of the structure for equality.
There are several ways to provide these elements:
-
Overload
operator==inside the structure and specializestd::hashfor your structure. This is the most common and recommended approach.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; bool operator==(const MyStruct& other) const { return id == other.id && name == other.name; } }; // Specialization of std::hash for MyStruct namespace std { template <> struct hash<MyStruct> { size_t operator()(const MyStruct& obj) const { size_t h1 = hash<int>()(obj.id); size_t h2 = hash<std::string>()(obj.name); // Combine hashes return h1 ^ (h2 << 1); } }; } // Usage example in main int main() { std::unordered_map<MyStruct, int> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; MyStruct key3 = {1, "Alice"}; // Equivalent to key1 my_map[key1] = 10; my_map[key2] = 20; // Access with an equivalent key if (my_map.count(key3)) { // my_map[key3] will give 10 } return 0; } -
Provide hash and comparison functions as separate template parameters when declaring
unordered_map. This is less convenient if you frequently use the structure as a key, as you need to specify the comparator and hasher types each time.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; }; // Separate hash function struct MyStructHash { size_t operator()(const MyStruct& obj) const { size_t h1 = std::hash<int>()(obj.id); size_t h2 = std::hash<std::string>()(obj.name); return h1 ^ (h2 << 1); } }; // Separate comparison function (or functor) struct MyStructEqual { bool operator()(const MyStruct& lhs, const MyStruct& rhs) const { return lhs.id == rhs.id && lhs.name == rhs.name; } }; // Usage example in main int main() { std::unordered_map<MyStruct, int, MyStructHash, MyStructEqual> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; my_map[key1] = 10; my_map[key2] = 20; return 0; }
Important points:
- Correctness of the hash function: For any two keys
aandb, ifa == b, thenhash(a)must be equal tohash(b). The reverse is not required (hash collisions are allowed). - Hash function quality: A good hash function distributes hash values evenly for different keys, minimizing collisions and improving performance (
O(1)on average). - Const correctness: The comparison operators and hash function should be
constas they should not modify the key object.