C ++ 14为关联容器中的等效find操作引入了Compare::is_transparent
。
template< class K > iterator find( const K& x );
template< class K > const_iterator find( const K& x ) const;
查找带有键的元素,该元素与值x进行比较。 如果这个重载只参与重载解析 qualified-is Compare :: is_transparent有效并表示类型。它 允许调用此函数而不构造Key
的实例
由于不再构造Key
的临时实例,因此这些实例可能更有效。
似乎没有等效的无序容器。
为什么没有Compare::key_equal
/ Compare::hash_equal
?
我认为在无序容器中有效查找例如字符串文字会相对简单吗?
template<>
struct hash<string>
{
std::size_t operator()(const string& s) const
{
return ...;
}
// hash_equal=true allows hashing string literals
std::size_t operator()(const char* s) const
{
return ...;
}
};
答案 0 :(得分:10)
比较相等的键应产生相同的哈希值。同时使散列函数和谓词和脱钩,使一个或两个异构,可能容易出错。
最近的论文P0919r2提出了以下示例:
std::hash<long>{}(-1L) == 18446744073709551615ULL
std::hash<double>{}(-1.0) == 11078049357879903929ULL
尽管-1L
和-1.0
比较相等,但某些与所选相等比较逻辑不符的异构哈希函数可能会产生不同的值。本文添加了支持异构查询的功能模板-
find
,count
,equal_range
和contains
-但在满足以下要求时[unord.req]/p17使它们可用:
如果 qualified-id
Hash::transparent_key_equal
有效并且表示类型([temp.deduct]),则该程序的格式不正确:
- qualified-id
Hash::transparent_key_equal::is_transparent
无效或不表示类型,或者Pred
与equal_to<Key>
或Hash::transparent_key_equal
的类型不同。成员函数模板
find
,count
,equal_range
和contains
不得参与重载解析,除非 qualified-id { {1}}有效,表示类型([temp.deduct])。
在这种情况下,Hash::transparent_key_equal
会覆盖默认谓词(Hash::transparent_key_equal
)并用于(透明)相等性检查,以及std::equal_to<Key>
本身用于(透明)哈希。
在这些情况下,下面的透明函数对象可用于启用异构查询:
Hash
struct string_equal
{
using is_transparent = void;
bool operator()(const std::string& l, const std::string& r) const
{
return l.compare(r) == 0;
}
bool operator()(const std::string& l, const char* r) const
{
return l.compare(r) == 0;
}
bool operator()(const char* l, const std::string& r) const
{
return r.compare(l) == 0;
}
};
struct string_hash
{
using transparent_key_equal = string_equal; // or std::equal_to<>
std::size_t operator()(const std::string& s) const
{
return s.size();
}
std::size_t operator()(const char* s) const
{
return std::strlen(s);
}
};
和string_equal
都是透明的比较器,可用作std::equal_to<>
的{{1}}。
在哈希函数类定义中具有此类型别名(或类型定义本身)清楚,它是一个有效的谓词,可以与特定的哈希逻辑配合使用,而两者不能发散。这样的无序集合可以声明为:
transparent_key_equal
或:
string_hash
任何一个都将使用std::unordered_set<std::string, string_hash> u;
和std::unordered_set<std::string, string_hash, string_hash::transparent_key_equal> u;
。
答案 1 :(得分:4)
如果您观看来自CppCon的Grill the committee视频,他们会解释为什么会发生这样的事情:没有人为之奋斗。
C ++由委员会标准化,但该委员会需要社区的意见。有人必须写论文,回应批评,去参加会议等等......然后可以对该功能进行投票。该委员会并不只是坐在那里发明语言和图书馆功能。它只讨论并投票给那些提出来的人。