使用标准库类型作为QHASH或QSET中的键
Using standard library types as keys in QHash or QSet
qt需要在QT的QHash
模板中使用密钥类型使用的qHash
超载。根据文档,重载必须是"类型的名称空间"。但这是一个问题,因为在C 中,将新的过载添加到std
名称空间中是未定义的行为。仅将过载添加到全局名称空间也不起作用。
最小示例:
#include <QHash>
#include <string>
//namespace std { // when adding to namespace std it compilies but that is not allowed
static uint qHash(const std::u32string &key, uint seed) noexcept {
return static_cast<uint>(std::hash<std::u32string>{}(key));
}
//}
QHash<std::u32string, int> h;
int main(int argc, char **argv) {
h.insert(std::u32string(), 5);
}
生成的错误消息相当长,我省略了尝试过的候选人列表(它们不包含字符串过载)
In file included from /usr/include/x86_64-linux-gnu/qt5/QtCore/qglobal.h:83:0,
from /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h:43,
from /usr/include/x86_64-linux-gnu/qt5/QtCore/QCoreApplication:1,
from ../test.cpp:1:
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h: In instantiation of ‘uint qHash(const T&, uint) [with T = std::__cxx11::basic_string<char32_t>; uint = unsigned int]’:
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h:920:18: required from ‘QHash<K, V>::Node** QHash<K, V>::findNode(const Key&, uint*) const [with Key = std::__cxx11::basic_string<char32_t>; T = int; QHash<K, V>::Node = QHashNode<std::__cxx11::basic_string<char32_t>, int>; uint = unsigned int]’
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhash.h:760:27: required from ‘QHash<K, V>::iterator QHash<K, V>::insert(const Key&, const T&) [with Key = std::__cxx11::basic_string<char32_t>; T = int]’
../qttui/testtui2.cpp:15:33: required from here
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h:110:40: error: no matching function for call to ‘qHash(const std::__cxx11::basic_string<char32_t>&)’
Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
~~~~~^~~
/usr/include/x86_64-linux-gnu/qt5/QtCore/qcompilerdetection.h:1144:43: note: in definition of macro ‘Q_DECL_NOEXCEPT_EXPR’
# define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
^
In file included from /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h:47:0,
from /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject.h:49,
from /usr/include/x86_64-linux-gnu/qt5/QtCore/qcoreapplication.h:46,
from /usr/include/x86_64-linux-gnu/qt5/QtCore/QCoreApplication:1,
from test.cpp:4,
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h:72:52: note: candidate: constexpr uint qHash(char, uint)
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
^~~~~
/usr/include/x86_64-linux-gnu/qt5/QtCore/qhashfunctions.h:72:52: note: no known conversion for argument 1 from ‘const std::__cxx11::basic_string<char32_t>’ to ‘char’
错误消息中的代码是此(据我在全局名称空间中说明):
template<typename T> inline uint qHash(const T &t, uint seed)
Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) // <---- qhashfunctions.h:110
{ return qHash(t) ^ seed; }
和:
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, uint *ahp) const
{
uint h = 0;
if (d->numBuckets || ahp) {
h = qHash(akey, d->seed); // <---- qhash.h:920
if (ahp)
*ahp = h;
}
return findNode(akey, h);
}
将过载放入正在查找的QT名称空间中。
更具体地说,必须将其注入到ADL-Oug-lookaup尝试的命名空间中。这可能涉及追踪错误的命名空间。
如果您正在设计图书馆并想避免此问题,则应创建一个专门解决此问题的名称空间。
创建两个功能:internal_qHash
和qHash
。
namespace mylibrary {
namespace hash_support {
struct qhash_tag {};
uint qHash( qhash_tag, int const& t, uint seed ) { /* TODO */ }
}
using ::mylibrary::hash_support::qhash_tag;
template<class T>
constexpr uint internal_qHash( T const& t, uint seed) {
using ::mylibrary::hash_support::qHash;
return qHash( qhash_tag{}, t, seed );
}
namespace hash_adl_blocking {
template<class T>
constexpr uint qHash( T const& t, uint seed ) {
return ::mylibrary::internal_qHash( t, seed );
}
}
using ::mylibrary::hash_adl_blocking::qHash;
}
现在使用mylibrary::qHash
使用mylibrary::hash_support
和T
的任何关联名称空间。
如果我们想检测Sfinae,必须完成更多的工作。
在此模型中,您要为无法将功能注入namespace mylibrary::hash_support
的命名空间的过载。
QT可能已经在为qHash(int, uint)
做类似的事情。查看QT定义的位置,如果您定义了std
超载,则应起作用。
qhash_tag
强制将2相名称查找重新考虑在点qHash
处注入mylibrary::hash_support
中的新符号,用于给定类型。
相关文章:
- 如何使用 std::string 作为 QHash 的键?
- 在类中初始化 QHash
- 如何覆盖 qHash() 函数?
- 已将 QSet 填充为可选参数
- 通过与现有 QHash 连接来初始化 const QHash
- 通过带有成员函数指针的 QHash 调用成员函数的正确方法
- 在 QSet 中插入元素<QString>并检索 ,删除 QSet 的最后一项
- QHash 存储大量数据
- 为我的类编写自定义 qhash() 函数
- 使用标准库类型作为QHASH或QSET中的键
- 有效地测试 QSet 是否包含元素,如果不存在,则插入
- QSet<func 指针> 不由 gcc 编译
- 如何初始化QString的常数QSET
- 使用 QSet 作为 Qt 映射容器中的键
- 遍历 QHash 并提取重复值的键时遇到问题
- 在Qt中使用带有QSet和boost::tuples::tuple的模板没有匹配错误
- Qhash-热以获取随机键和价值
- QSet in QMap or QHash
- 如何为 QSet<SomeClass*> 容器编写 qHash?
- QSet: qHash和自定义类错误