在shared_ptr的unordered_set中查找值

Deq*_*ing 3 c++ shared-ptr unordered-set

我想在unordered_set中找到一个值,但是失败了:

typedef std::shared_ptr<int> IntPtr;

std::unordered_set<IntPtr> s;
s.insert(std::make_shared<int>(42));

bool found = s.find(std::make_shared<int>(42)) != s.end();
cout<<std::boolalpha<<found<<endl; // false
Run Code Online (Sandbox Code Playgroud)

曾尝试过但仍然没有工作.

namespace std {
  template <> struct hash<IntPtr> {
    size_t operator()(const IntPtr& x) const noexcept {
      return std::hash<int>()(*x);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

知道如何让它有效吗?

Use*_*ess 6

您存储了一个指向整数的指针.当你在集合中查找项目时,你不是在比较(指向的)整数,而是指针本身.

当您为搜索分配新的整数对象的指针时,它将不会比较相等,因为它是一个不同的整数对象(即使它存储相同的值).

你的选择是:

  1. 不要在集合中存储指向整数的指针,只需直接存储整数.

    然后,你的密钥是42,并且搜索42将找到它,因为整数按值进行比较

  2. 存储指针并使用自定义散列和比较器来比较指向的整数而不是指针.

    您不应该(尝试)std使用您的哈希特化来污染命名空间,并且它无论如何都不够(哈希用于存储桶查找,但仍然会将存储桶内的密钥进行比较KeyEqual).只需为容器指定它们即可.

#2的示例代码:

#include <cassert>
#include <memory>
#include <unordered_set>

struct Deref {
    struct Hash {
        template <typename T>
        std::size_t operator() (std::shared_ptr<T> const &p) const {
            return std::hash<T>()(*p);
        }
    };
    struct Compare {
        template <typename T>
        size_t operator() (std::shared_ptr<T> const &a,
                           std::shared_ptr<T> const &b) const {
            return *a == *b;
        }
    };
};

int main() {
    std::unordered_set<std::shared_ptr<int>> sp;
    auto p = std::make_shared<int>(42);
    sp.insert(p);
    assert(sp.find(p) != sp.end()); // same pointer works
    assert(sp.find(std::make_shared<int>(42)) == sp.end()); // same value doesn't

    // with the correct hash & key comparison, both work
    std::unordered_set<std::shared_ptr<int>, Deref::Hash, Deref::Compare> spd;
    spd.insert(p);
    assert(spd.find(p) != spd.end());
    assert(spd.find(std::make_shared<int>(42)) != spd.end());
}
Run Code Online (Sandbox Code Playgroud)