Defining custom hash function and equality function for unordered_map

Alex319 picture Alex319 · Jan 20, 2010 · Viewed 12.6k times · Source

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")?

Answer

Omnifarious picture Omnifarious · Jan 20, 2010

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.