受け入れられた解決策であるにもかかわらず、私のものは間違っているため、以下のRichard Hodgesの回答をお読みください。
unordered_sets
ハッシュベースであるため、std::weak_ptr データ型のハッシュ関数オブジェクトを提供する必要があります。
unordered_set template-parameters を見ると
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::weak_ptr<> の std::hash<> 特殊化が存在しないことを示しているため、そのために独自のハッシュ関数を提供する必要があります。
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;