I'd like to find a value in unordered_set, but failed:
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
Had tried following but still not working.
namespace std {
template <> struct hash<IntPtr> {
size_t operator()(const IntPtr& x) const noexcept {
return std::hash<int>()(*x);
}
};
}
Any idea how to make it works?
You stored a pointer to an integer. When you look up items in the set, you're not comparing the (pointed-to) integer, but the pointer itself.
When you allocate a new pointer to a new integer object for the search, it won't compare equal, because it's a different integer object (even though it stores the same value).
Your options are:
don't store pointers to integers in your set, just store the integers directly.
Then, your key is 42
, and searching for 42
will find it, because the integers are compared by value
store pointers and use a custom hash and comparator to compare the pointed-at integers instead of the pointers.
You shouldn't (try to) pollute std
namespace with your hash specialization, and it's not sufficient anyway (the hash is used for bucket lookup, but keys are still compared with KeyEqual
inside the bucket). Just specify them for your container.
Example code for #2:
#include <cassert>
#include <memory>
#include <unordered_set>
namespace 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());
}