Last active
January 25, 2016 02:18
-
-
Save PhDP/85fe01ac7cc4a4a93a74 to your computer and use it in GitHub Desktop.
unordered_set using the shared_ptr's value
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <memory> | |
#include <unordered_set> | |
#include <unordered_map> | |
#include <boost/functional/hash.hpp> | |
class my_class { | |
std::string m_name; | |
double m_a, m_b, m_c; // random stuff | |
size_t m_hash; | |
public: | |
my_class(const std::string name, double a = 0.0, double b = 0.0, double c = 0.0); | |
auto hash() const -> size_t; | |
friend auto operator==(const my_class&, const my_class&) -> bool; | |
friend auto operator!=(const my_class&, const my_class&) -> bool; | |
friend auto operator<<(std::ostream&, const my_class&) -> std::ostream&; | |
}; | |
my_class::my_class(const std::string name, double a, double b, double c) | |
: m_name(name), m_a(a), m_b(b), m_c(c) { | |
m_hash = 42; | |
boost::hash_combine(m_hash, m_name); | |
boost::hash_combine(m_hash, m_a); | |
boost::hash_combine(m_hash, m_b); | |
boost::hash_combine(m_hash, m_c); | |
} | |
auto my_class::hash() const -> size_t { | |
return m_hash; | |
} | |
auto operator==(const my_class &a, const my_class &b) -> bool { | |
return a.m_hash == b.m_hash; | |
} | |
auto operator!=(const my_class &a, const my_class &b) -> bool { | |
return a.m_hash != b.m_hash; | |
} | |
auto operator<<(std::ostream &os, const my_class &c) -> std::ostream& { | |
os << c.m_name << '(' << c.m_a << ", " << c.m_b << ", " << c.m_c << ')'; | |
return os; | |
} | |
/** | |
\brief Hashes a pointer to an object using the object's hash method. | |
*/ | |
template <typename PTR> | |
struct ptr_hasher { | |
auto operator()(const PTR &x) const -> size_t { | |
return x->hash(); | |
} | |
}; | |
/** | |
\brief Compares two pointers by their object's value. | |
*/ | |
template <typename PTR> | |
struct ptr_eq { | |
auto operator()(const PTR &x, const PTR &y) const -> bool { | |
return *x == *y; | |
} | |
}; | |
template <typename PTR> | |
using ptr_hash_set = std::unordered_set<PTR, ptr_hasher<PTR>, ptr_eq<PTR>>; | |
template <typename PTR, typename T> | |
using ptr_hash_map = std::unordered_map<PTR, T, ptr_hasher<PTR>, ptr_eq<PTR>>; | |
auto main() -> int { | |
auto x = std::make_shared<my_class>(my_class("Foo", 0.5, 0.7)); | |
auto y = std::make_shared<my_class>(my_class("Foo", 0.5, 0.7)); | |
std::cout << "x == y: " << (x == y) << std::endl; | |
auto elems0 = std::unordered_set<std::shared_ptr<my_class>> { x, y, x }; | |
std::cout << "Size of elems0: " << elems0.size() << std::endl; | |
auto elems1 = ptr_hash_set<std::shared_ptr<my_class>> { x, y, x }; | |
std::cout << "Size of elems1: " << elems1.size() << std::endl; | |
auto z = std::make_shared<my_class>(my_class("Foo", 0.5, 0.7, 0.0)); | |
std::cout << "z found in elems0: " << (elems0.find(z) != elems0.end()) << std::endl; | |
std::cout << "z found in elems1: " << (elems1.find(z) != elems1.end()) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment