【发布时间】:2013-07-16 08:04:36
【问题描述】:
当我编译以下代码时,我看到了与 Hash 相关的错误。
int F_no_meaningA(unordered_set<vector<int>>& setVec, vector<int>& vec)
{
setVec.insert(vec);
return 1;
}
int main()
{
vector<int> W{2, 3, 7};
unordered_set<vector<int>> setVec;
}
$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
$ g++ $1.cpp -o $1 -g -Wall -Weffc++ -pedantic -std=c++0x
/tmp/ccCQFQ4N.o:在函数中 `std::__detail::_Hash_code_base
, std::vector >, std::_Identity > >, std::equal_to > >, 标准::哈希 > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, 假>::_M_hash_code(std::vector > const&) 常量':/usr/include/c++/4.6/bits/hashtable_policy.h:753:未定义 参考
std::hash<std::vector<int, std::allocator<int> > ::operator()(std::vector<int, std::allocator<int> >) const' /tmp/ccCQFQ4N.o: In functionstd::__detail::_Hash_code_base , std::vector >, std::_Identity > >, std::equal_to > >, 标准::哈希 > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(std::__detail::_Hash_node >, false> const*, unsigned int) const': /usr/include/c++/4.6/bits/hashtable_policy.h:763:未定义的引用 到`std::hash > ::operator()(std::vector >) const' collect2: ld 返回 1 个退出状态
那么,我引入下面自己的Hash,问题就解决了。
问题 1> 我们什么时候应该为std::unordered_set 提供我们自己的哈希?
我们什么时候应该为std::unordered_set 提供我们自己的等价函数?
struct HashVector : unary_function<vector<int>, vector<int>::size_type> {
vector<int>::size_type operator()(const vector<int>& vec) const {
vector<int>::size_type sum = 0;
for(int i : vec) {
sum = sum*37 + hash<int>()(i);
}
return sum;
}
};
int F_no_meaningB(unordered_set<vector<int>, HashVector>& setVec, vector<int>& vec)
{
setVec.insert(vec);
return 1;
}
int main()
{
vector<int> W{2, 3, 7};
unordered_set<vector<int>, HashVector> setVec;
}
警告:基类‘struct std::unary_function, unsigned int>' 有一个非虚析构函数 [-Weffc++]
问题 2> 为什么 g++ 会抱怨 struct HashVector 并带有上述警告?
谢谢
【问题讨论】:
-
因为
vector<int>没有内置哈希? -
所以你的意思是编译器不够聪明,无法使用 std::hash
迭代遍历向量中的所有元素? -
这不是“聪明”或“不聪明”的问题。您的解决方案是 a 解决方案,而不是散列容器的 the 解决方案。您可能还想要任何其他行为。顺便说一句,请查看
Boost.Hash和hash_combine和hash_range。 -
@q0987 只要容器中存储的类型不是标准提供specialization 的类型,您就需要提供自己的哈希函数。如果您可以使用 Boost,它会提供
hash_range,它将遍历容器并生成哈希。