By failing I mean it is giving a repeated value for different group of double. The three doubles are x, y and z of a vertex. I have a list of vertices and using the hash created from the doubles as a key in the map. I was wondering if a more reliable hash combine function for this specific application exists.

 template <class T> inline void hash_combine(std::size_t& seed, T const& v) { seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } 

1 Answer

I have a list of vertices and using the hash created from the doubles as a key in the map.

Not the best use of a hash, in the sense of what std::hash or boost::hash represents.

You're looking for uniqueness. A hash in this sense is not unique.

I was wondering if a more reliable hash combine function for this specific application exists.

Not unless the hash space has a 1:1 correlation with the space of possible values of z, y and z - which essentially means using the vertex itself as the identifier.

Summary:

If you want a container indexed by unique vertices, you may want to consider a std::unordered_map. You will need to provide an equality operator.

An example:

#include <boost/functional/hash.hpp> // see below #include <tuple> #include <unordered_map> #include <string> // a simple Vertex class struct Vertex { double x, y, z; }; // a useful general-purpose accessor auto as_tuple(Vertex const& v) -> decltype(auto) { return std::tie(v.x, v.y, v.z); } // equality implemented in terms of tuple, for simplicity bool operator==(Vertex const& l , Vertex const& r) { return as_tuple(l) == as_tuple(r); } // hash_value implemented in terms of tuple, for consistency and simplicity std::size_t hash_value(Vertex const& v) { using boost::hash_value; return hash_value(as_tuple(v)); } // the boring bit - injecting a hash specialisation into the std:: namespace // but let's derive from boost's hash class, which is much better // in that it allows easy hashing using free functions namespace std { template<> struct hash<::Vertex> : boost::hash<::Vertex> {}; } using vertex_map = std::unordered_map<Vertex, std::string>; int main() { auto m = vertex_map(); m[{0, 0, 0}] = "Sol"; m[{1, 3, 5}] = "Mars"; m[{100.4, 343.2, 92.44}] = "Pluto"; } 

Note: The numbers above are in Zargian NonLinear Megaunits - you won't find them in any Earthbound textbook on the Solar System.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.