C++ std::hash<>
has some standard specializations用于固定大小的基本类型,以及std::string
家族,这是唯一一个具有可变内存大小的家族(还有std::vector<bool>
,这里不关心)
一旦我们倾向于散列多个变量或一个缓冲区,我们需要实现一个散列算法,这是很难记住,很容易出错。std::string
可以用作缓冲区(我知道std::vector<std::byte>
更好),如果我们在其中存储utf-8字符串(包含ASCII以外的字节),它可能也是哈希的。
这样的缺点是什么:
std::string hash_wrapper(4 * 4, '\0');
int* write_ptr = reinterpret_cast<int*>(hash_wrapper.data());
write_ptr[0] = val1;
write_ptr[1] = val2;
write_ptr[2] = val3;
write_ptr[3] = val4;
std::unordered_map<std::string, int> ht;
ht[hash_wrapper] = val;
1条答案
按热度按时间qvk1mo1f1#
您的代码违反了严格别名。
你的代码非常不清楚它在做什么。
散列Map的关键在于它们是Map,散列Map是从一个模糊的转换字符串类型到数据,而不是从一个合理的键到数据。
我的建议是:
1.写一个散列组合器,或者使用其他人发布的散列组合器(具有适当的属性/权限),如boost的散列组合器。
1.扩展到散列组合器,它采用任意散列序列并将其组合。
现在写一个简短的库。
现在,只要你需要一个自定义的运行时哈希,就在类型的命名空间中为你的自定义类型重写
runtime_hash
。通过这项工作
我可以添加哈希支持:
有了这个
只是工作。
runtime_hash
函数是通过ADL找到的。更重要的是,std::vector<bob::alice>
有哈希支持,std::tuple<bob::alice>
和std::tuple<std::set<bob::alice>, bob::alice>
等也是如此。如果你写任何其他复合类型并像我做的std
容器一样给予它,那些包含bob::alice
的容器也可以工作。上面这个实用程序代码的大小和复杂性都足够短,因此,在缓冲区和指针以及未定义的别名之间浪费时间是绝对不值得的。
请注意,我将其命名为
runtime_hash
--这既使其具有某种独特的命名(对ADL很重要),也强调了无法保证此哈希在程序的不同执行过程中是稳定的。您不能以这种方式依赖std
哈希的稳定性,因为它们不提供这种保证。上面的代码是直接输入到答案中的,从未被编译过,所以它可能至少包含一个tpyo。