我们可以在C ++中的类中定义哈希码方法吗 [英] Can we define hashcode method within a class in C++

查看:119
本文介绍了我们可以在C ++中的类中定义哈希码方法吗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在C ++中实现一个类,并且我希望每个类都具有自己的哈希码实现(基本上是将其用作unordered_map& unordered_set中的键)

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)

例如:

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);
    }
    */
};

现在,假设我想在unordered_map中使用它

Now, suppose I want to use this in an unordered_map like

int main(){
    unoredered_map<CustomClass, int> m;
}

我有两个选择,

i)使用模板专门化功能将std名称空间中的哈希码注入

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.)在实例化每次创建unordered_map(或unordered_set)时都指定此函数,即

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);
  }
};

并在实例化unordered_map的同时,提供了此结构.

and while instantiating the unordered_map, I have provide this struct.

int main(){
    unoredered_map<CustomClass, int, HashSpecialer> m;
}

我找到了两种方法,这使我感到困惑:(i)污染std名称空间,(ii)每次我实例化unordered_map

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

是否有可能在类定义本身中提供哈希码功能,如我在上面代码片段的注释部分所述


注意:在java中,我们可以重写类中的hashCode()方法,并且可以实现此功能.一旦重写了hashCode()方法,以后就不必担心它了.

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.

推荐答案

我认为,解决您的问题的方法是调整您对美观的C ++程序的理解.

I think the solution to your problem is to adjust your understanding of what is an aesthetically pleasing C++ program.

专门化std::hash不会污染std名称空间,相反,您应该考虑std::hash是用于控制unordered_map如何与您的类一起工作的自定义点.

A specialization of std::hash doesn't pollute the std namespace, instead you should consider that std::hash is the customization point for controlling how unordered_map works with your class.

这种专门化是类接口的一部分(并且可以是该类的朋友),其方式与operator +()之类的二进制运算符应该是非成员函数完全相同,并且仍然是该类的一部分.界面.

Such a specialization is part of the interface of the class (and can be a friend of the class) in exactly the same way as binary operators like operator +() should be a non-member functions, and still be part of the interface.

这篇关于我们可以在C ++中的类中定义哈希码方法吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆