C++ 如何散列QVariant?
我需要使用C++ 如何散列QVariant?,c++,qt,qvariant,stdhash,C++,Qt,Qvariant,Stdhash,我需要使用QList作为std::unordered_map的键。这样做的目的是通过在唯一键列上建立索引来优化对数据表的搜索 所以我做了这个代码。它不完整,但列出了表键列中出现的一些基本数据类型: #include <unordered_map> #include <string> //std::hash #include <functional> //std::size_t #include <cstddef> // Hashing method
QList
作为std::unordered_map
的键。这样做的目的是通过在唯一键列上建立索引来优化对数据表的搜索
所以我做了这个代码。它不完整,但列出了表键列中出现的一些基本数据类型:
#include <unordered_map>
#include <string>
//std::hash
#include <functional>
//std::size_t
#include <cstddef>
// Hashing method for QVariantList
namespace std {
template <>
struct hash<QList<QVariant>>
{
std::size_t operator()(const QList<QVariant>& k) const
{
using std::size_t;
using std::hash;
using std::string;
size_t hash_num = 0;
Q_FOREACH(var, k) {
// Make hash of the primitive value of the QVariant
switch(var.type()) {
case QVariant::String : {
hash_num = hash_num^hash<string>(var.toString().toStdString());
break;
}
case QVariant::Char :
case QVariant::ULongLong :
case QVariant::UInt :
case QVariant::LongLong :
case QVariant::Int : {
hash_num = hash_num^hash<long long>(var.toLongLong());
break;
}
case QVariant::Double : {
hash_num = hash_num^hash<double>(var.toDouble());
break;
}
}
}
return hash_num;
}
};
}
#包括
#包括
//散列
#包括
//标准:尺寸
#包括
//QVariantList的哈希方法
名称空间标准{
模板
结构散列
{
std::size\u t运算符()(常量QList&k)常量
{
使用std::size\u t;
使用std::hash;
使用std::string;
大小\u t哈希\u num=0;
Q_FOREACH(var,k){
//对QVariant的原语值进行哈希
开关(变量类型()){
大小写QVariant::字符串:{
hash_num=hash_num^hash(变量toString().tostString());
打破
}
案例QVariant::Char:
案例QVariant::ULongLong:
案例QVariant::UInt:
案例QVariant::LongLong:
案例QVariant::Int:{
hash_num=hash_num^hash(变量toLongLong());
打破
}
案例QVariant::Double:{
hash_num=hash_num^hash(变量toDouble());
打破
}
}
}
返回hash_num;
}
};
}
显然,我不喜欢整个开关的事情。它是相当长和丑陋的代码,只考虑基本类型。我宁愿对分配给QVariant
的内部数据的内存数据进行散列。或者,更好的方法是使用一些Qt的散列方法
有没有一种半可靠的*方式来散列任何QVariant而不将其转换为基元类型
*我知道复杂的对象可能隐藏在QVariant后面,但这会导致冲突的情况非常罕见,所以我不必在意。给自己找一个QByteArray
+QBuffer
+QDataStream
基本上将QVariant
序列化到QByteArray
然后简单地散列字节数组中的原始字节。Qt已经为QByteArray
实现了一个qHash
函数,所以您已经准备好了
通过使用足够的预分配字节重用相同的QByteArray
,可以最大限度地提高效率,以避免重新分配。您可以将整个内容包装在一个VariantHasher
类中,在每次新哈希之前,只需对缓冲区进行seek(0)
,只对pos()
字节数进行哈希,而不是对整个内容进行哈希
class QVariantHasher {
public:
QVariantHasher() : buff(&bb), ds(&buff) {
bb.reserve(1000);
buff.open(QIODevice::WriteOnly);
}
uint hash(const QVariant & v) {
buff.seek(0);
ds << v;
return qHashBits(bb.constData(), buff.pos());
}
private:
QByteArray bb;
QBuffer buff;
QDataStream ds;
};
QVariantHasher类{
公众:
QVariantHasher():buff(&bb)、ds(&buff){
bb.储备(1000);
buff.open(QIODevice::WriteOnly);
}
uint散列(常量QVariant&v){
buff.seek(0);
ds您是否已经尝试过Qt的方法,如QVariant::toHash()
?@Jean-Emmanuel将变量转换为QHash
,并且不散列基础值。@Jean-EmmanueltoHash
尝试将QVariant
转换为QHash
,这是一个散列映射,而不是散列。我的意思是,我对文档执行了Ctrl+F操作,此外,我还阅读了它的内容。如果您不担心的话关于性能:使用QDataStream
将QVariant
写入QByteArray
并使用qHash(const-QByteArray&)
函数。我还没有发现一种简单的方法可以获得QVariant
的“原始”表示。您可以使用类似的访问者,然后将返回值传递给qHash()
。在这种特殊情况下,我非常关心性能。你认为你的建议会比我制作的开关慢吗?好吧,除非你将它们并排比较,否则无法判断。你需要它有多快?在我的系统上,它在15213纳秒内散列4个整数4个实数4个字符串和4个QRECT。还有一个修道院考虑到效率因素,您不必实现一个巨大的开关,它适用于所有支持序列化的类型。@TomášZato首先,如果您要使用qHash
函数,您可以使qHash
开关更友好。例如var.toString().toststring()
可能比qHash(var.toString())慢
因为您在堆中创建了一个带有分配的临时对象。第二步:试着比较一下。没有人知道QDataStream
如何序列化QVariant
。至少额外的QByteArray
可以有一个很长的分配/解除分配时间。@TomášZato您可以专门处理我们最常见的类型对问题中的代码进行重新编译,然后返回到这个答案的方法,作为对您不想专门处理的类型的回退和未来验证。