请阅读下面的Richard Hodges答案,因为我的答案是不正确的,尽管它是公认的解决方案。
由于unordered_sets
是基于散列的,因此您必须为std::weak_ptr 数据类型提供散列函数对象。
如果您查看 unordered_set 模板参数
template<class Key,
class Hash = std::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<Key> >
class unordered_set;
您会注意到 std::unordered_set 为您提供了默认的 std::hash<> 模板参数。但由于 std::hash 只提供特定数据类型集的特化,您可能必须提供自己的。
您引用的错误消息告诉您, std::hash<> 不存在 std::weak_ptr<> 的专门化,因此您必须为此提供自己的散列函数:
template<typename T>
struct MyWeakPtrHash : public std::unary_function<std::weak_ptr<T>, size_t> {
size_t operator()(const std::weak_ptr<T>& wp)
{
// Example hash. Beware: As zneak remarked in the comments* to this post,
// it is very possible that this may lead to undefined behaviour
// since the hash of a key is assumed to be constant, but will change
// when the weak_ptr expires
auto sp = wp.lock();
return std::hash<decltype(sp)>()(sp);
}
};
编辑:
您还需要提供一个相等函数,因为没有为 weak_ptr 提供 std::equal_to 。从Stackoverflow 上的“Equality-compare std::weak_ptr”采取一种可能的方法:
template<typename T>
struct MyWeakPtrEqual : public std::unary_function<std::weak_ptr<T>, bool> {
bool operator()(const std::weak_ptr<T>& left, const std::weak_ptr<T>& right)
{
return !left.owner_before(right) && !right.owner_before(left);
}
};
所有这些都为我们提供了以下信息:
std::unordered_set<std::weak_ptr<T>,
MyWeakPtrHash<T>,
MyWeakPtrEqual<T>> wpSet;