I am trying to implement a class in C++, and I want each class to have its own implementation of hashcode(basically to use it as a key in unordered_map
& unordered_set
)
for eg:
class CustomClass{
int a;
vector<int> b;
string c;
bool operator ==(const CustomClass& o) const{
return ((a == o.a) && (b == o.b) && (c == o.c));
}
/*
Is it possible to define the hashcode function here instead of defining it outside the class.
size_t operator()() const {
// Some custom logic for calculating hash of CustomClass using
// the hash Values of its individual fields
std::size_t h = 0;
for(int& t : b){
h = (h ^ std::hash<int>()(t)) << 1;
}
return (h^(std::hash<int>()(a) << 1))^( std::hash<string>()(c) << 1);
}
*/
};
Now, suppose I want to use this in an unordered_map like
int main(){
unoredered_map<CustomClass, int> m;
}
I have two options,
i) Inject the hashcode in std namespace with Template specialization
namespace std {
template <> struct hash<CustomClass> {
size_t operator()(const CustomClass& o) const {
// Some custom logic for calculating hash of CustomClass using
// the hash Values of its individual fields
size_t h = 0;
for(int& t : o.b){
h = (h ^ std::hash<int>()(t)) << 1;
}
return (h^(std::hash<int>()(o.a) << 1))^( std::hash<string>()(o.c) << 1);
}
};
}
OR
ii.) Specify this function while creating the unordered_map
(or unordered_set
) every time while instantiating it, i.e
struct HashSpecialer {
std::size_t operator()(const CustomClass& o) const {
std::size_t h = 0;
for(int& t : o.b){
h = (h ^ std::hash<int>()(t)) << 1;
}
return (h^(std::hash<int>()(o.a) << 1))^( std::hash<string>()(o.c) << 1);
}
};
and while instantiating the unordered_map
, I have provide this struct.
int main(){
unoredered_map<CustomClass, int, HashSpecialer> m;
}
I find both the methods, confusing to use (i) Pollutes the std namespace and (ii) makes it hard by remembering to provide the HashSpecializer every time I instantiate an unordered_map
Is it possible to provide the hashcode function within the class definition itself , as I described in the commented section in the code snippet above
Note : In java , we can override the hashCode() method in the class and we could achieve this functionality. Once I override the hashCode() method, I need not worry about it later.
public class CustomClass {
int a;
List<Integer> b;
String c;
// I Let my IDE generate these methods :D
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CustomClass that = (CustomClass) o;
if (a != that.a)
return false;
if (b != null ? !b.equals(that.b) : that.b != null)
return false;
return c != null ? c.equals(that.c) : that.c == null;
}
// This one too :D
@Override public int hashCode()
{
int result = a;
result = 31 * result + (b != null ? b.hashCode() : 0);
result = 31 * result + (c != null ? c.hashCode() : 0);
return result;
}
}
I am looking for something like this as this proves to be very handy.