The signature of the unordered_map class is this:
template<class Key,
class Ty,
class Hash = std::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, Ty> > >
class unordered_map;
Your example works because the default Pred, std::equal_to<>, by default checks for equality using operator==. The compiler finds your foo::operator== member function and uses that.
std::hash doesn't have any specialisation which will call a member function on your class, so you can't just add a member to foo with a custom hash. You will need to specialise std::hash instead. If you want that to call a member function on foo, go ahead. You'll end up with something like this:
struct foo
{
size_t hash() const
{
// hashing method here, return a size_t
}
};
namespace std
{
// Specialise std::hash for foo.
template<>
class hash< foo >
: public unary_function< foo, size_t >
{
public:
size_t operator()( const foo& f )
{
return f.hash();
}
};
}