如何使用 std::string 作为 QHash 的键?
How to use std::string as key of QHash?
我想使用std::string
作为QHash
的键:
QHash<std::string, QString> m_hash;
m_hash.insert("ABC", "DEF");
我实现了所需的qHash:
inline qHash(const std::string& key, uint seed = 0)
{
qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
}
一切都使用 MSVC 正确编译,但 gcc 生成以下错误:
错误:调用
qHash(const std::__cxx11::basic_string<char>&)
没有匹配函数
我应该如何解决这个问题?
Qt 6.1 及更高
版本开箱即用地支持使用std::string
作为键,因为Qt现在使用std::hash
作为qHash
的后备。
Qt 6.1 之前
简答题
在std
命名空间内定义qHash
函数可能会解决编译器错误,但将函数添加到std
命名空间是未定义的行为。所以,这是不允许的。
解决方法是将std::string
包装在帮助程序类[1]中:
class MyHashString : public std::string {};
QHash<MyHashString, QString> m_hash;
m_hash.insert("ABC", "DEF");
inline qHash(const MyHashString& key, uint seed = 0)
{
qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
}
长答案
如此错误报告中所述,必须在std::string
的命名空间内定义qHash
函数:
这记录在C++标准中。它称为参数相关查找。它说搜索非限定的qHash(T(将在T的命名空间中找到它。
因此,所需qHash
的正确定义是:
namespace std
{
inline qHash(const std::string& key, uint seed = 0)
{
qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
}
}
Qt文档中也提到了这一点:
QHash的键类型除了是可分配的数据类型之外,还有其他要求:它必须提供operator==((,并且该类型的命名空间中还必须有一个qHash((函数,该函数返回键类型的参数的哈希值。
但是,向std
命名空间添加函数是未定义的行为。因此,人们坚持使用非理想的解决方法。
延伸阅读
- https://en.wikipedia.org/wiki/Argument-dependent_name_lookup
- https://en.cppreference.com/w/cpp/language/adl
- 关于
qHash
重载的有趣文章:https://www.kdab.com/how-to-declare-a-qhash-overload/
相关文章:
- 使用一个考虑到std::map中键值的滚动或换行的键
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 使用字符数组作为 Map 中的键
- 如何在C++中访问有序映射中的键的范围/间隔?
- 查找不存在的键时,unordered_map返回什么
- 如何使用 std::string 作为 QHash 的键?
- 是否有像地图这样的C++结构,但我得到的不是值的键,而是值的句柄?
- C++ 映射的键/值的用户自定义名称?
- 比较它们之间的元素并获取公共值的键
- 更改多重映射容器中所有元素的键值
- 使用 nullptr 作为 std::unordered_map 的键有什么后果吗?
- CPP 使用不存在的键访问映射
- 为什么 Boost multi_index只修改第一个索引的键时对第二个索引进行比较?
- 找不到最新插入到 std::map 中的键
- 将相同的键添加到低序映射
- 从 AVL 树中删除指向 1 个或多个值的键
- 通过从矢量中获取键和与映射中的键对应的值来创建映射
- 使用标准库类型作为QHASH或QSET中的键
- 遍历 QHash 并提取重复值的键时遇到问题
- Qt循环通过QHash<QString,QString>返回它的键值对