我不理解正确的事情。我的印象是unordered_set不允许基于哈希值的重复元素。
我有一个结构,具有std :: hash的特化,看起来允许重复,虽然我已经手动检查了它
AddEdge ( const std::shared_ptr<Relation> relation, const std::shared_ptr<Concept> concept )
{
auto edge = std::make_shared<Edge>( (Edge){ relation, concept } );
auto res = _edges.insert ( edge );
return res.second;
}
重载函数完全相同但反转参数
这是struct Edge的散列方式:
namespace std
{
template<> struct hash<shared_ptr<Edge>>
{
size_t operator()( const shared_ptr<Edge> & ptr ) const
{
size_t from = 0;
size_t to = 0;
if ( auto node = std::dynamic_pointer_cast<Concept>( ptr->from ) )
from = hash<shared_ptr<Concept>>()( node );
else if ( auto node = std::dynamic_pointer_cast<Relation>( ptr->from ) )
from = hash<shared_ptr<Relation>>()( node );
if ( auto node = std::dynamic_pointer_cast<Concept>( ptr->to ) )
to = hash<shared_ptr<Concept>>()( node );
else if ( auto node = std::dynamic_pointer_cast<Relation>( ptr->to ) )
to = hash<shared_ptr<Relation>>()( node );
return hash<size_t>()( from + to );
}
};
}
容器保存在:
std::unordered_set<std::shared_ptr<Edge>> _edges;
当我这样做时:
graph2->AddEdge( sea_node, is_node );
graph2->AddEdge( is_node, blue_node );
我明白了:
Edge [sea,is] hash = 10017731961838884781
Edge [is,blue] hash = 11178184051384786808
我第二次尝试完全一样,我得到相同的哈希值,但是,当我检查边缘时,我现在有4条边而不是2条。
我做错了什么?
编辑:课程概念&amp; Relation具有相同类型的哈希函数:
namespace std
{
template<> struct hash<shared_ptr<Concept>>
{
size_t operator()( const shared_ptr<Concept> & ptr ) const
{
return hash<string>()( ptr->asToken()->value() ) + hash<int>()( ptr->TokenIndex() ) + hash<string>()( "Concept" );
}
};
}
更有意思的是,我添加Edges时的输出会生成相同的哈希值,但是会添加重复的Edge。
答案 0 :(得分:9)
unordered_set将不允许基于哈希值的重复元素
不,unordered_set
通过比较值而不是那些值†的哈希值来避免重复。
每个共享指针的“值”将会有所不同,因为它们引用了不同的对象。
您实际上可以通过将自己的函数作为KeyEqual
的{{1}}模板参数来更改此行为:
unordered_set
†如果template<
class Key,
class Hash = std::hash<Key>, // <-- you've been looking at this
class KeyEqual = std::equal_to<Key>, // <-- instead of this
class Allocator = std::allocator<Key>
> class unordered_set;
中只允许一个具有给定哈希的值,则(a)您将无法添加任何真正导致哈希冲突的值,(b)完全不需要整个哈希冲突解决机制。