【发布时间】:2021-04-22 22:05:42
【问题描述】:
我想为我正在编写的一个类创建一个散列函数,并且我想让散列函数成为该类的朋友,这样我就不必编写不必要的 getter 方法。为此,我遵循了this SO post 中接受的答案。但我希望能够将对象插入std::unordered_set 或boost::unordered_set。所以我是这样写的:
#include <iostream>
#include <unordered_set>
#include <boost/functional/hash.hpp>
#include <boost/unordered_set.hpp>
class Vec;
namespace std { // line [c]
template<>
struct hash<Vec> {
public:
size_t operator()(const Vec &v) const;
};
}
class Vec {
private:
std::vector<int> v;
public:
friend size_t std::hash<Vec>::operator ()(const Vec& v) const; // line [d]
friend bool operator == (const Vec& lhs, const Vec& rhs) { return lhs.v == rhs.v; }
};
namespace std { // line [e]
size_t hash<Vec>::operator()(const Vec &v) const {
return boost::hash<std::vector<int> >()(v.v);
}
}
int main() {
Vec v;
std::unordered_set<Vec> s1; // line [f]
s1.insert(v); // line [g]
boost::unordered_set<Vec> s2; // line [a]
s2.insert(v); // line [b]
}
但我发现在尝试编译它时出现了一长串错误。然后,当我删除行 [a,b] 时,它按预期编译并运行。然后,我没有删除行[a,b],而是(1)将它们留在里面,(2)删除行[f,g],(3)将行[c,d,e]更改为boost而不是std,再次代码会正确编译。最后,我尝试在 boost 命名空间中重复声明哈希结构:
#include <iostream>
#include <unordered_set>
#include <boost/functional/hash.hpp>
#include <boost/unordered_set.hpp>
class Vec;
namespace std {
template<>
struct hash<Vec> {
public:
size_t operator()(const Vec &v) const;
};
}
// new: {
namespace boost {
template<>
struct hash<Vec> {
public:
size_t operator()(const Vec &v) const;
};
}
// }
class Vec {
private:
std::vector<int> v;
public:
friend size_t std::hash<Vec>::operator ()(const Vec& v) const;
// new: {
friend size_t boost::hash<Vec>::operator ()(const Vec& v) const;
// }
friend bool operator == (const Vec& lhs, const Vec& rhs) { return lhs.v == rhs.v; }
};
namespace std {
size_t hash<Vec>::operator()(const Vec &v) const {
return boost::hash<std::vector<int> >()(v.v);
}
}
// new: {
namespace boost {
size_t hash<Vec>::operator()(const Vec &v) const {
return boost::hash<std::vector<int> >()(v.v);
}
}
// }
int main() {
Vec v;
std::unordered_set<Vec> s1;
s1.insert(v);
boost::unordered_set<Vec> s2;
s2.insert(v);
}
我的问题是:为什么我必须在 std 和 boost 命名空间中创建一个散列函数才能让它工作?我会说我对原因有直觉,但我想要一个非常详细的解释。而且我想要任何替代解决方案来解决上述代码段中有很多重复代码的事实(但不是像 boost::unordered_set<Vec, my_vec_class_hash> 这样的东西,因为我希望它是“自动的”)。
【问题讨论】:
-
就个人而言,我不会专门化
boost::或std::而是编写名为VecHasher的类,然后使用whatever::unordered_set<Vec, VecHasher> -
您甚至可以使用别名,例如
using unordered_vec_set = whatever::unordered_set<Vec, VecHasher>; -
为什么需要对无序集同时使用 boost 和 std 模板?听起来像是 XY 问题。
-
我不了解 boost,但专业化
std::hash按标准明确是 allowed。这是一种简洁明了的方式,没有任何问题。 -
@Ranoiaetep 不需要,看我的回答。
标签: c++ boost hash namespaces