Using QString as the key in std::unordered_map

Put the hash implementation in a header, and make sure that you include that header everywhere the map is used.

A trivial implementation that forwards to qHash should be sufficient:

#include <QHash>
#include <QString>
#include <functional>

namespace std {
  template<> struct hash<QString> {
    std::size_t operator()(const QString& s) const noexcept {
      return (size_t) qHash(s);
    }
  };
}

Even though std::size_t is larger than unsigned int on common 64 bit platforms, and thus the hash doesn't change across its full length - this isn't a problem. The standard places no such requirement on an std::hash implementation.


The problem is that there is no std::hash<QString>() specialization. It's easy enough to define your own with reasonably good performance based on the dbj2 algorithm:

#include <QString>
#include <unordered_map>

namespace std
{
    template<> struct hash<QString>
    {
        std::size_t operator()(const QString& s) const noexcept
        {
            const QChar* str = s.data();
            std::size_t hash = 5381;

            for (int i = 0; i < s.size(); ++i)
                hash = ((hash << 5) + hash) + ((str->row() << 8) | (str++)->cell());

            return hash;
        }
    };
}

include that in files which use a QString in a std::unordered_map and the error goes away.