为私有成员类专门化std::hash

4

我有一个类(称其为Outer),它有一个私有成员类(Inner)。我想在无序的标准容器中存储Outer::Inner的实例,因此我想专门化std::hash<Outer::Inner>

但是,在编写以下内容时:

namespace std {
    template<>
    struct hash<Outer::Inner> {
        std::size_t operator()(const Outer::Inner &arg) const
        {
            return std::hash<int>()(arg.someSpecialProperty);
        }
    };
}

编译器报错:
error: 'Inner' is a private member of 'Outer'
            std::size_t operator()(const Outer::Inner &p) const
                                                ^

我尝试通过遵循这个答案来使std::hash成为友元结构体,但是失败了:前向声明Outer::Inner无法使用:

error: use of undeclared identifier 'Outer'

那么,如果我想要做的事情是可能的,我应该如何继续呢?

1
参考这篇文章:http://stackoverflow.com/questions/8760181/friend-within-private-nested-class,似乎你的情况是不可能的,因为你不能在std::hash中添加友元关系... - AntiClimacus
@AntiClimacus 因为我不是宣布原始的 std::hash 模板的人,对吧? - The Paramagnetic Croissant
这就是原因,没错。 - AntiClimacus
@AntiClimacus 哦,谢谢。嗯,那真是令人失望。 :-( (如果你感觉需要的话,请毫不犹豫地写下答案。) - The Paramagnetic Croissant
1
你不能只是在 Outer 内部声明 friend struct std::hash<Inner>; 吗?(可能在声明或定义 Inner 之后。)然后再进行特化定义。 - Alan Stokes
2个回答

8
明白了!解决方案是使用您自己的函数对象,而不是专门为std::hash进行特化。
struct A
{
  A() { v.insert(std::make_pair(B(1), 6)); }

private:
  struct B
  {
    B(int i = 0) : m_i(i) { }

    int m_i;
  };

  struct HashB { std::size_t operator()(const B& b) const { return b.m_i; } };
  struct EqualB { bool operator()(const B&b1, const B&b2) const { return b1.m_i == b2.m_i; } };


  std::unordered_map<B, int, HashB, EqualB> v;
};

5

既然这是一个私有内部类型,我认为你在封闭类中有一个私有或受保护的std::unordered_map成员。如果是这样的话,只需编写一个私有内部哈希函数对象,并将其作为std::unordered_map的第三个参数传递即可解决问题,这应该是最简单的解决方案。


是的,我最终做到了这一点。我想这不是最漂亮的解决方案。 - The Paramagnetic Croissant

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