Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining custom hash function and equality function for unordered_map

I am trying to define a type of unordered_map that has a custom hash function and equality comparison function. The function prototypes of these functions are as follows:

//set<Vertex3DXT*> is the type of the key; Cell3DXT* is the type of the value
size_t VertexSetHashFunction(set<Vertex3DXT*> vertexSet); //hash function
bool SetEqual(set<Vertex3DXT*> a, set<Vertex3DXT*> b); //equality

I have these function prototypes declared and then I try to declare the type as follows:

typedef std::tr1::unordered_map<set<Vertex3DXT*>, Cell3DXT*, VertexSetHashFunction, SetEqual> CellDatabaseMapType;

But it says that the VertexSetHashFunction and SetEqual are not valid template type arguments. The documentation is confusing because it doesn't say exactly what type the template arguments are supposed to be - am I just supposed to give it the function as I did here, or is there some other kind of object that encapsulates the function (because the documentation does talk about the "hash function object type")?

like image 484
Alex319 Avatar asked Jan 20 '10 06:01

Alex319


People also ask

Which hash function is used in unordered_map?

The unordered_map::hash_function() is a built in function in C++ STL which is used to get the hash function. This hash function is a unary function which takes a single argument only and returns a unique value of type size_t based on it.

How do you hash an unordered set?

An unordered_set is implemented using a hash table where keys are hashed into indices of a hash table so that the insertion is always randomized.

Is unordered_map and HashMap same?

Yes, HashMap in java and unordered_map in c++ stl are more or less the same… you can store pointers in java too(Don't forget, in java, everything you deal with is a reference)… hence, HashMap also serves your purpose.

How do you pass an unordered map in a function?

Just replace the int with something like unordered_map<int, int> . You're going to want to pass it with a const reference if you don't need to modify it. Don't use the const if you want to modify the original object that was used to call the function. Save this answer.


1 Answers

Those functions should be declared as an operator () in a class, unfortunately. Like this:

class VertexSetHashFunction {
  public:
    ::std::size_t operator ()(const ::std::set<Vertex3DXT*> &vertexSet) const;
};
class SetEqual {
  public:
    bool operator ()(const ::std::set<Vertex3DXT*> &a, const ::std::set<Vertex3DXT*> &b) const;
};

You do not have to modify the arguments to be const references, but I would highly recommend it. Making a copy of a ::std::set is relatively expensive and you shouldn't do it unless you absolutely have to.

The trailing const is just because the operator doesn't actually modify the class state at all, mostly because there isn't any. It's just nice to say so explicitly.

Alternately, you could define your own specialization of the ::std::hash template. I would actually recommend this if there is one standard way you want that particular set hashed because this template is used by default if you do not supply a hash function to unordered_map or unordered_set and anything else that needs a hash function.

like image 115
Omnifarious Avatar answered Sep 29 '22 02:09

Omnifarious