使用QString作为std :: unordered_map中的键

Nic*_*aus 7 c++ qt stdhash c++17

我试图QString用作a中的键std::unordered_map,但是我得到了错误:

错误C2280:'std :: hash <_Kty> :: hash(const std :: hash <_Kty>&)':尝试引用已删除的函数

我无法切换, QHash因为地图的值类型是不可复制的.有没有办法让这项工作?

Rei*_*ica 14

hash实现放在标题中,并确保在使用映射的任何位置包含该标头.

一个简单的实现,转发到qHash应该是足够的:

#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);
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

即使std::size_tunsigned int常见的64位平台更大,因此散列不会在其整个长度上发生变化 - 这不是问题.该标准对std::hash实施没有这样的要求.


Nic*_*aus 6

问题是没有std::hash<QString>()专业化.基于dbj2算法,可以很容易地定义自己的性能并且具有相当好的性能:

#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;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

包括在a QString中使用a的文件中,std::unordered_map并且错误消失.

  • @RSahu肯定可以,但由于utf8转换和内存分配的unicode,它不会那么高效. (3认同)
  • 甚至可能"返回qHash(s)". (3认同)