C++ 在std::无序_映射中使用QString作为键

C++ 在std::无序_映射中使用QString作为键,c++,qt,c++17,stdhash,C++,Qt,C++17,Stdhash,我试图使用QString作为std::unordered_map中的键,但是我得到了错误: 错误C2280:'std::hash::hash(const std::hash&'):试图引用已删除的函数 我无法切换到QHash,因为映射的值类型是不可复制的。有什么方法可以使这项工作正常吗?问题是没有std::hash()专门化。很容易根据算法定义您自己的性能相当好的算法: #include <QString> #include <unordered_map> namesp

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

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


我无法切换到
QHash
,因为映射的值类型是不可复制的。有什么方法可以使这项工作正常吗?

问题是没有
std::hash()
专门化。很容易根据算法定义您自己的性能相当好的算法:

#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;
        }
    };
}
#包括
#包括
名称空间标准
{
模板结构哈希
{
std::size_t运算符()(常量QString&s)常量noexcept
{
常量QChar*str=s.data();
std::size\u t hash=5381;
对于(int i=0;i

std::unordered_map
中使用
QString
的文件中包含该值,错误就会消失。

散列
实现放在头中,并确保在使用映射的任何地方都包含该头

转发到
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);
    }
  };
}
#包括
#包括
#包括
名称空间标准{
模板结构哈希{
std::size_t运算符()(常量QString&s)常量noexcept{
返回(大小)qHash;
}
};
}

即使在普通64位平台上,
std::size\t
大于
unsigned int
,因此哈希值不会在其整个长度上发生变化-这不是问题。标准对
std::hash
实现没有这样的要求。

在较新版本的Qt中,std::hash似乎是为QStri定义的ng,因此您可以直接将其与std::unordered_map一起使用。(它在我的机器上与Qt 5.14一起使用。)

您可以将其简化为
返回std::hash()(s.TostString());
@RSahu当然可以,但由于unicode到utf8的转换和内存分配,它的性能不会那么好。甚至可能
返回qHash(s)
@NicolasHolthaus,没错。就像前面所说的,只返回qHash值更简单。