gpt4 book ai didi

c++ - 为什么我必须为每个命名空间定义一个哈希函数作为 unordered_set?

转载 作者:行者123 更新时间:2023-12-04 07:45:52 26 4
gpt4 key购买 nike

我想为我正在编写的类创建一个散列函数,我想让散列函数成为类的 friend ,这样我就不必编写不必要的 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 启用 ADL 的自定义点 hash_value,您可以大大减少困惑。 :

class Vec {
private:
std::vector<int> v;

friend size_t hash_value(const Vec& v) {
return boost::hash_range(begin(v.v), end(v.v));
}
friend bool operator==(const Vec& lhs, const Vec& rhs) {
return lhs.v == rhs.v;
}
};

In fact, the hash function can be even simpler with return boost::hash_value(v.v); in this case.


这已经足以使 Boost 的无序容器与您的类型一起工作:
boost::unordered_set<Vec> s2;
s2.insert(v);
添加标准支持
现在这不是问题:
template <> struct std::hash<Vec> : boost::hash<Vec> {};
现场演示
Live On Coliru
#include <boost/functional/hash.hpp>
#include <boost/unordered_set.hpp>
#include <iostream>
#include <unordered_set>

class Vec {
private:
std::vector<int> v;

friend size_t hash_value(const Vec& v) {
return boost::hash_value(v.v);
//return boost::hash_range(begin(v.v), end(v.v));
}
friend bool operator==(const Vec& lhs, const Vec& rhs) {
return lhs.v == rhs.v;
}
};

template <> struct std::hash<Vec> : boost::hash<Vec> {};

int main() {
Vec v;
std::unordered_set<Vec> s1;
s1.insert(v);
boost::unordered_set<Vec> s2;
s2.insert(v);
}

关于c++ - 为什么我必须为每个命名空间定义一个哈希函数作为 unordered_set?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67202331/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com