我认为大部分工作都在这里完成,最后只剩下一些细节。继续阅读。
我正在尝试编写粘合代码,以使用MurmurHash3哈希C++中GMP库的大整数(mpz_t
和mpz_class
)。我这样做是为了以后在std::unordered_map<mpz_class, int>
中使用它们。
我希望代码能够以有用的方式针对32位和64位系统进行编译,并且在需要128位系统时易于扩展。为此,我编写了MurmurHash3_size_t()
函数,该函数调用MurmurHash3的正确哈希函数,然后将结果转换为size_t
。我假设size_t
在32/64/128位系统中具有正确的位大小。 (我不知道此假设是否有用。)这部分代码可以很好地编译。
当我想定义 std::hash
函数时出现问题。我的代码出现编译器错误(请参见代码中的注释)。如何正确编写这些std::hash
函数以及如何调用它们?
(click to view MurmurHash3.h)
文件hash_mpz.cpp
:
#include "hash_mpz.h"
#include <gmpxx.h>
#include "MurmurHash3.h"
size_t MurmurHash3_size_t(const void *key, int len, uint32_t seed) {
#if SIZE_MAX==0xffffffff
size_t result;
MurmurHash3_x86_32(key, len, seed, &result);
return result;
#elif SIZE_MAX==0xffffffffffffffff
size_t result[2];
MurmurHash3_x64_128(key, len, seed, &result);
return result[0] ^ result[1];
#else
#error cannot determine correct version of MurmurHash3, because SIZE_MAX is neither 0xffffffff nor 0xffffffffffffffff
#endif
}
namespace std {
size_t hash<mpz_t>::operator()(const mpz_t &x) const {
// found 1846872219 by randomly hitting digits on my keyboard
return MurmurHash3_size_t(x->_mp_d, x->_mp_size * sizeof(mp_limb_t), 1846872219);
}
size_t hash<mpz_class>::operator()(const mpz_class &x) const {
// compiler error in next statement
// error: no matching function for call to ‘std::hash<__mpz_struct [1]>::operator()(mpz_srcptr)’
return hash<mpz_t>::operator()(x.get_mpz_t());
}
}
最佳答案
找到了适合我的解决方案:
namespace std {
size_t hash<mpz_srcptr>::operator()(const mpz_srcptr x) const {
// found 1846872219 by randomly typing digits on my keyboard
return MurmurHash3_size_t(x->_mp_d, x->_mp_size * sizeof(mp_limb_t),
1846872219);
}
size_t hash<mpz_t>::operator()(const mpz_t &x) const {
return hash<mpz_srcptr> { }((mpz_srcptr) x);
}
size_t hash<mpz_class>::operator()(const mpz_class &x) const {
return hash<mpz_srcptr> { }(x.get_mpz_t());
}
}
然后,您可以使用哈希函数,如下所示:
#include <iostream>
#include <gmpxx.h>
#include <unordered_map>
#include "hash_mpz.h"
using namespace std;
int main() {
mpz_class a;
mpz_ui_pow_ui(a.get_mpz_t(), 168, 16);
cout << "a : " << a << endl;
cout << "hash(a): " << (hash<mpz_class> { }(a)) << endl;
unordered_map<mpz_class, int> map;
map[a] = 2;
cout << "map[a] : " << map[a] << endl;
return 0;
}
输出:
a : 402669288768856477614113920779288576
hash(a): 11740158581999522595
map[a] : 2
评论被赞赏。
关于c++ - 如何编写和调用std::hash? -用于gmp的mpz_class和mpz_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62452712/