Discover how to resolve issues with explicitly defaulted constructors in C+ + when using `unordered_map` with struct keys. Learn to implement a custom hash function!
---
This video is based on the question https://stackoverflow.com/q/64678512/ asked by the user 'Daniel' ( https://stackoverflow.com/u/12664906/ ) and on the answer https://stackoverflow.com/a/64678615/ provided by the user 'Ted Lyngmo' ( https://stackoverflow.com/u/7582247/ ) at 'Stack Overflow' website. Thanks to these great users and Stackexchange community for their contributions.
Visit these links for original content and any more details, such as alternate solutions, latest updates/developments on topic, comments, revision history etc. For example, the original title of the Question was: Explicitly defaulted default constructor is implicitly deleted because of unordered_map used with a struct as key
Also, Content (except music) licensed under CC BY-SA https://meta.stackexchange.com/help/l...
The original Question post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license, and the original Answer post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license.
If anything seems off to you, please feel free to write me at vlogize [AT] gmail [DOT] com.
---
Understanding the Problem: Default Constructor Deletion in C+ +
When working with C+ + , developers often encounter the unordered_map when storing key-value pairs in a non-duplicate format. However, an issue arises when you try to define a struct as the key of an unordered_map, particularly if you plan to use a default constructor. If you're using a struct for your keys and don't provide the proper hashing functionality, C+ + will implicitly delete the default constructor of your class, as proven by errors like this:
[[See Video to Reveal this Text or Code Snippet]]
In this guide, we will explore why this happens, and how to effectively implement a solution that allows the use of the default constructor alongside an unordered_map with struct keys.
Problem Explanation
Why Does This Happen?
The issue stems from the fact that the keys in an unordered_map need to be hashable. This means that the compiler needs to be able to generate a hash value for the key type—in this case, the struct Edge. Since a hash function is not provided by default for user-defined types, the default constructor for your Graph class ends up being deleted, thus preventing its instantiation.
Here's a quick overview of the provided Graph class:
[[See Video to Reveal this Text or Code Snippet]]
In the above code, the default constructor of Graph cannot be used because the unordered_map can't be constructed without a hash function defined for the Edge struct.
The Solution: Implementing a Hash Function
To resolve this issue, you need to ensure that the Edge struct is hashable. This can be achieved in two ways: by specializing the std::hash class template for the Edge struct or by providing a custom functor for hashing when creating the unordered_map. Below, we'll explore how to implement both solutions.
Option 1: Specialization of std::hash
If you choose to make the Edge struct public, you can add the following specialization of std::hash:
[[See Video to Reveal this Text or Code Snippet]]
In this specialization, you need to provide the logic to compute a unique hash based on the properties of the Edge. A typical approach involves using custom logic akin to the one above, with hash functions combining the different attributes of the struct.
Option 2: Using a Custom Hash Functor
If you prefer to keep the Edge struct private, a more encapsulated solution is to use a custom hash functor. This alters the definition of the unordered_map to include a functor that calculates the hash when needed, as shown below:
[[See Video to Reveal this Text or Code Snippet]]
In this implementation, you define a struct edge_hasher which overloads the operator() to compute a hash that combines the hashes of the individual properties of Edge. This configuration allows the Graph class to have its default constructor without any compilation errors.
Conclusion
Overall, as seen from this discussion, using unordered_map with a struct as a key demands a hashing mechanism for the structure type employed. Whether you opt for specializing std::hash or implementing a custom hash functor, both methods are valid and will enable you to utilize your Graph class with a fully functioning default constructor. Always remember: to use custom types in a hash table, you must provide the necessary hashing logic!
If you've encountered similar issues, or have further questions about using unordered_map, feel free to share your experiences in the comments below!
Информация по комментариям в разработке