用户自定义类的哈希函数。如何交朋友? :)

18

我有一个类C,其中有一个私有数据成员string* ps
现在,我想要一个unordered_map<C, int>,为此我需要一个自定义的哈希函数。

根据C++参考文献,我可以这样做:

namespace std {
  template<>
  class hash<C> {
  public:
    size_t operator()(const C &c) const
    {
      return std::hash<std::string>()(*c.ps);
    }
  };
}

问题在于我似乎无法使operator()C成为朋友,以便我可以访问ps

我尝试过这个:

class C;
template<>
class std::hash<C>;
class C{
  //...
  friend std::hash<C>::operator ()(const C&) const; // error: Incomplete type 
};
// define hash<C> here.

但它说不完整的类型在嵌套名称限定符中...

我也不能改变定义的顺序,因为如果类C后定义,hash<C>就无法知道ps

我在这里做错了什么?如何在不公开ps的情况下解决这种情况?

3个回答

25

试试这个:

class C;
namespace std {
  template<>
  struct hash<C> {
  public:
    size_t operator()(const C &c) const; // don't define yet
  };
}
class C{
  //...
  friend size_t std::hash<C>::operator ()(const C&) const;
};
namespace std {
  template<>
  size_t hash<C>::operator()(const C &c) const {
    return std::hash<std::string>()(*c.ps);
  }
}

或者是这个:
class C;
template<>
struct std::hash<C>;
class C{
  friend struct std::hash<C>; // friend the class, not the member function
};

我还没有编译,所以可能会有语法错误。


是的,没错,谢谢,我马上会标记为已接受。与此同时,我也意识到自己有多傻![尴尬] :) - Barney Szabolcs
4
对于 MSVC2012,你需要在 size_t hash<C>::operator() 的实现中移除 template<>,否则会出现 error C2910 cannot be explicitly specialized - Jichao
在不删除 template<> 的情况下,在 Gcc 上,我得到了 error: template-id ‘operator()<>’ for ‘std::size_t std::hash<C>::operator()(const C&) const’ does not match any template declaration。+1 给 Jichao。 - Conchylicultor

0

交友更简单的方式:

class C {
  template <typename T> friend class std::hash;
};

即使C在自己的命名空间中或是一个嵌套类,这也能正常工作,因为std::hash不需要被提前声明。


-2
我建议添加如下方法
class C
{
....
public:  const string* get_ps() const { return ps; }
....
};

并在您的哈希专业化中使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接