C++11 我应该将用户定义类型的专用std::hash放在哪里
我搜索了很多页面,我想我已经知道如何编写std::hash。但我不知道该把它放在哪里 这里给出了一个例子 但是,我在文件C++11 我应该将用户定义类型的专用std::hash放在哪里,c++11,hash,unordered-set,user-defined,C++11,Hash,Unordered Set,User Defined,我搜索了很多页面,我想我已经知道如何编写std::hash。但我不知道该把它放在哪里 这里给出了一个例子 但是,我在文件Instance\u management.h的命名空间ca中定义了我的类型Instance。我想在另一个类的同一个文件中使用InstanceManager。因此,我编写了以下代码: namespace std { template <> struct hash<ca::Instance> { size_t operato
Instance\u management.h
的命名空间ca
中定义了我的类型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
名称空间std
{
模板结构哈希
{
size\u t运算符()(常量ca::实例和实例)常量
{
std::size\u t seed=0;
//这里有一些散列值计算。
返回种子;
}
};
}//名称空间std
但是我应该把它放在哪里呢?我尝试了很多地方,但都失败了
我正在使用visual studio 2013。我试图将前面的代码放在一些位置,但都未能编译
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
//位置1
命名空间ca
{
类实例{…}
类实例管理器
{
//…还有其他一些事情。
私有无序集;
}
}
//地点2
不要专门研究std::hash
,而是编写自己的hash函数对象(请参见下面的Edge\u hash
),并使用两个模板参数声明您的无序集
#include <unordered_set>
#include <functional>
namespace foo
{
// an edge is a link between two nodes
struct Edge
{
size_t src, dst;
};
// this is an example of symmetric hash (suitable for undirected graphs)
struct Edge_Hash
{
inline size_t operator() ( const Edge& e ) const
{
static std::hash<size_t> H;
return H(e.src) ^ H(e.dst);
}
};
// this keeps all edges in a set based on their hash value
struct Edge_Set
{
// I think this is what you're trying to do?
std::unordered_set<Edge,Edge_Hash> edges;
};
}
int main()
{
foo::Edge_Set e;
}
#包括
#包括
名称空间foo
{
//边是两个节点之间的链接
结构边
{
尺寸src,dst;
};
//这是对称散列的一个示例(适用于无向图)
结构边散列
{
内联大小\u t运算符()(常数边和e)常数
{
静态std::hash H;
返回H(e.src)^H(e.dst);
}
};
//这将根据其哈希值将所有边保留在一个集中
结构边集合
{
//我想这就是你想做的?
std::无序的集合边;
};
}
int main()
{
foo::边集e;
}
相关职位包括:
有几种方法
专门化
std::hash
在代码中,确保std::hash
专门化前面紧跟着实例
类定义,后面紧跟着使用它的无序集
容器
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
在这里,您只需将自己的哈希函数传递给容器,然后就可以使用它了。缺点是您必须显式地键入自己的容器
使用hash\u append
然而,请注意,标准提案目前尚待审查。该方案的特点是采用了一种更优越的设计,即使用一个通用哈希函数,该函数通过模板参数(实际的哈希算法)对任意字节流进行哈希
有关更多详细信息,请参阅作者@HowardHinnant在CppCon14(,)上的演示。和提供的完整源代码。谢谢大家
我找到了原因并以某种方式解决了问题:当我定义实例时,visual studio接受了实例哈希
。由于我正在将set
的用法更改为unordered\u set
,因此在尝试获取const\u迭代器时,我忘记了指定InstanceHash
,所以这次编译器尝试使用std::hash
东西,但失败了。但是编译器没有使用const\u迭代器
定位该行,因此我在定义实例时错误地认为它不接受InstanceHash
我还尝试专门化类实例的std::hash
。但是,这种专门化至少需要声明classca::Instance
及其一些成员函数来计算散列值。经过此专门化之后,类ca::InstanceManage
的定义将使用它
我现在通常把几乎所有类和成员函数的声明和实现放在一起。所以,我需要做的是把<代码> CA<代码>代码命名空间范围分成2个部分,并在中间放置“代码> STD{StuttHuth{H.{}} /Cuth.<我的C++代码库。因此,instance_management.h文件中没有main()。我必须尝试将所有内容放在名称空间中,包括类实例和使用无序_集的InstanceManager。然而,许多页面上都说,鼓励在std名称空间中为用户定义的类型放置专门的std::hash。我编写了代码片段,并试图将其放在同一文件中的某个位置,但未能成功编译instance_management.h文件。当我将您的代码放在单独的.h文件中时,visual studio成功编译了它。然而,当我用同样的方法编写代码并使用“private:unordered\u set instances”时,我得到的错误是:像:<代码>错误C23 38:C++标准不提供这种类型的哈希。<代码> >代码>参见引用类模板实例化“STD::Hash”被编译1 > 1 > [ 1>KKTY=CA:实例1 > ] />代码>。编译器似乎不接受我指定的InstanceHash。将其放入实例管理.h
有什么错?我会向上投票+10,因为这太棒了,但它并没有真正回答OP是否接受它?@Sh3ljohn有工作代码实现了这一点,并完全避免使用std::hash
。在你的回答中,陈述H(e.src)^H(e.dst)
是薄弱环节。它可能会破坏哈希函数的所有好属性。@TemplateRex实际上,我不知道“标准建议”是什么意思。这是否意味着某一天的提案将是C++标准?编译器支持如何?VC++会支持它吗?@TemplateRex我尝试了使用std::hash\u append在visual studio 2013中选择code>,然后按F1
键进行hash\u append
。联机文档系统未找到有关的信息
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
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);
}
};
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_);
}
}