I wanted to have something like
unordered_set>> us;
but even without pair:
#includ
You could implement it like this, based on boost::hash_combine
for a sensible calculation of hashes:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <unordered_set>
namespace
{
// a little helper that should IMHO be standardized
template<typename T>
std::size_t make_hash(const T& v)
{
return std::hash<T>()(v);
}
// adapted from boost::hash_combine
void hash_combine(std::size_t& h, const std::size_t& v)
{
h ^= v + 0x9e3779b9 + (h << 6) + (h >> 2);
}
// hash any container
template<typename T>
struct hash_container
{
size_t operator()(const T& v) const
{
size_t h=0;
for( const auto& e : v ) {
hash_combine(h, make_hash(e));
}
return h;
}
};
}
namespace std
{
// support for pair<T,U> if T and U can be hashed
template<typename T, typename U>
struct hash<pair<T, U>>
{
size_t operator()(const pair<T,U>& v) const
{
size_t h=make_hash(v.first);
hash_combine(h, make_hash(v.second));
return h;
}
};
// support for vector<T> if T is hashable
// (the T... is a required trick if the vector has a non-standard allocator)
template<typename... T>
struct hash<vector<T...>> : hash_container<vector<T...>> {};
// the same for map<T,U> if T and U are hashable
template<typename... T>
struct hash<map<T...>> : hash_container<map<T...>> {};
// simply add more containers as needed
}
int main()
{
std::unordered_set<std::vector<std::pair<int,int>>> us;
us.insert(std::vector<std::pair<int,int>>{{{42,0},{17,64}}});
std::cout << us.size() << std::endl;
std::cout << us.begin()->size() << std::endl;
std::cout << us.begin()->begin()->first << std::endl;
std::unordered_set<std::map<int,int>> usm;
std::map<int,int> m{{42,0},{17,64}};
usm.insert(m);
}
Live example
Note that there was a problem when combining Clang with libstdc++ which might affect you when specializing std::hash
. It has been fixed with GCC 4.8.2, but it is still visible on Coliru. If this is a problem in your case, you could disable the warning with -Wno-mismatched-tags
and Clang will no longer complain.
You should write a hasher for your types, for example:
class MyHash
{
public:
std::size_t operator()(const vector<pair<int,int>> &v) const
{
std::size_t x = 0;
for (auto &i : v)
x ^= std::hash<int>()(i.first) ^ std::hash<int>()(i.second);
return x;
}
};
int main()
{
unordered_set<vector<pair<int,int>>, MyHash> um;
}
Note: The hash function that I wrote is just an example, it can be replaced with another and better one.