如何计算 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_ptr
s中创建这些,因为没有强引用的弱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();}
};}
一个警告:使用别名构造函数可能会导致异常结果。由于相等性基于控制块相等性,而不是指针值。
所以我有使用 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_ptr
s中创建这些,因为没有强引用的弱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();}
};}
一个警告:使用别名构造函数可能会导致异常结果。由于相等性基于控制块相等性,而不是指针值。