为什么没有std :: is_transparent等价的无序容器?

时间:2015-10-27 16:21:32

标签: c++ c++14

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 ...;
    }
};

2 个答案:

答案 0 :(得分:10)

比较相等的键应产生相同的哈希值。同时使散列函数和谓词脱钩,使一个或两个异构,可能容易出错。

最近的论文P0919r2提出了以下示例:

std::hash<long>{}(-1L) == 18446744073709551615ULL
std::hash<double>{}(-1.0) == 11078049357879903929ULL

尽管-1L-1.0比较相等,但某些与所选相等比较逻辑不符的异构哈希函数可能会产生不同的值。本文添加了支持异构查询的功能模板-  findcountequal_­rangecontains-但在满足以下要求时[unord.req]/p17使它们可用:

  

如果 qualified-id Hash::transparent_­key_­equal有效并且表示类型([temp.deduct]),则该程序的格式不正确:

     
      
  • qualified-id Hash::transparent_­key_­equal::is_­transparent无效或不表示类型,或者
  •   
  • Predequal_­to<Key>Hash::transparent_­key_­equal的类型不同。
  •   
     

成员函数模板findcountequal_­rangecontains不得参与重载解析,除非 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 ++由委员会标准化,但该委员会需要社区的意见。有人必须写论文,回应批评,去参加会议等等......然后可以对该功能进行投票。该委员会并不只是坐在那里发明语言和图书馆功能。它只讨论并投票给那些提出来的人。