如何计算 std::weak_ptr 的哈希值?

How to compute hash of std::weak_ptr?

所以我有使用 std::weak_ptr 并将它们维护在 std::set 中的代码,并且工作得很好——并且在过去的 5 或 7 年里一直有效。最近我想 fiddle 在 std::unordered_set 中使用它们(好吧,实际上是在 f14::F14ValueSet 中),为此,我需要它的散列。目前还没有std::hash<std::weak_ptr>,那我该怎么办呢?

答案似乎是“只是对控制块进行哈希处理”,正如这个问题和回复所暗示的那样:Why was std::hash not defined for std::weak_ptr in C++0x?,但是我如何才能访问控制块?在 glibc 中,它位于 __weak_ptr<>::_M_refcount._M_pi-> 但这是私有的(并且是特定于实现的)。我还能做什么?

一个答案是“等一下”:maybe someday there will be a standard owner_hash() for std::weak_ptr,但我更喜欢现在可用的东西。

制作你自己的增强弱指针。

存储哈希值,支持==基于owner_before()

必须shared_ptrs中创建这些,因为没有强引用的弱ptr不能被散列以匹配它的所有者;这可能会创建两个增强的弱指针,它们比较相等但散列不同。

template<class T>
struct my_weak_ptr {
  // weak ptr API clone goes here.  lock() etc.

  // different ctor:
  my_weak_ptr(std::shared_ptr<T>const& sp){
    if(!sp) return;
    ptr=sp;
    hash = std::hash<T*>{}(sp.get());
  }
  std::size_t getHash()const{return hash;}
  friend bool operator<(my_weak_ptr const& lhs, my_weak_ptr const& rhs){
    return lhs.owner_before(rhs);
  }
  friend bool operator!=(my_weak_ptr const& lhs, my_weak_ptr const& rhs){
    return lhs<rhs || rhs<lhs;
  }
  friend bool operator==(my_weak_ptr const& lhs, my_weak_ptr const& rhs){
    return !(lhs!=rhs);
  }
private:
  std::weak_ptr<T> ptr;
  std::size_t hash=0;
};

这些具有稳定、合理的哈希值。虽然回收的对象指针会导致散列冲突,但只要它们不共享控制块,它们就不会相等。

namespace std{template<class T>struct hash<some_ns::my_weak_ptr<T>>{
  std::size_t operator()(my_weak_ptr<T> const& wp)const{return wp.getHash();}
};}

一个警告:使用别名构造函数可能会导致异常结果。由于相等性基于控制块相等性,而不是指针值。