我搜索了很多页面,我想我已经知道如何编写 std::hash 了。但我不知道把它放在哪里。
此处提供了一个示例 http://en.cppreference.com/w/cpp/utility/hash 。
但是,我在文件 Instance
的命名空间 ca
中定义了我的类型 instance_management.h
。我想在另一个类 unordered_set<Instance>
的同一个文件中使用 InstanceManager
。所以我写了以下代码:
namespace std
{
template <> struct hash<ca::Instance>
{
size_t operator()(const ca::Instance & instance) const
{
std::size_t seed = 0;
// Some hash value calculation here.
return seed;
}
};
} // namespace std
但是我应该把它放在哪里?我尝试了很多地方,但都失败了。
我使用的是visual studio 2013。我试图将以前的代码放在某些位置,但都无法编译它。
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
最佳答案
有几种方法。
专门的 std::hash
在您的代码中,确保您的 std::hash<Instance>
特化紧跟在 Instance
类定义之前,然后是使用它的 unordered_set
容器。
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
一个缺点是在将
std::hash<ca::Instance>
传递给其他函数时可能会遇到有趣的名称查找干扰。原因是 ca
的所有模板参数的关联命名空间 ( std::hash
) 可以在名称查找 (ADL) 期间使用。此类错误很少见,但如果发生,则很难调试。有关更多详细信息,请参阅 this Q&A。
将您的哈希值传递给
unordered_set
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
在这里,您只需将自己的哈希函数传递给容器并完成它。缺点是您必须明确键入您自己的容器。
使用
hash_append
但是请注意,N3980 标准提案目前正在等待审核。该提案具有更优越的设计,它使用通用散列函数,该函数将任意字节流通过其模板参数(实际散列算法)进行散列
template <class HashAlgorithm>
struct uhash
{
using result_type = typename HashAlgorithm::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
HashAlgorithm h;
using std::hash_append;
hash_append(h, t);
return static_cast<result_type>(h);
}
};
然后,用户定义的类 X 必须提供正确的
hash_append
,通过它它可以将自己呈现为字节流,准备好由通用哈希器进行哈希处理。class X
{
std::tuple<short, unsigned char, unsigned char> date_;
std::vector<std::pair<int, int>> data_;
public:
// ...
friend bool operator==(X const& x, X const& y)
{
return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
}
// Hook into the system like this
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
using std::hash_append;
hash_append(h, x.date_);
hash_append(h, x.data_);
}
}
有关更多详细信息,请参阅作者 @HowardHinnant 在 CppCon14 ( slides 、 video ) 上的演示。 author 和 Bloomberg 的完整源代码可用。
关于c++11 - 我应该在哪里放置用户定义类型的专用 std::hash,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32697636/