You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Entity类内重载的operator()无法作为unordered_map哈希器?

自定义结构体重载operator()作为哈希函数无法用于默认unordered_map的问题

我在自定义C++结构体Entity中重载了operator()作为哈希函数,同时重载==运算符用于相等判断。但实例化默认哈希器的unordered_map<const Entity, bitset<24>>时编译报错;将哈希逻辑提取至独立的KeyHasher结构体则可正常运行。请问该operator()存在什么问题?

代码示例

#include <bitset>
#include <unordered_map>
using namespace std;

struct Entity {
  
  string name;
  
  size_t operator()(const Entity& k) const noexcept 
  { return std::hash<string>{}(k.name); }
  
  bool operator== (const Entity& e) const noexcept 
  { return e.name == name; }

};

struct KeyHasher {
  size_t operator()(const Entity& k) const noexcept
  { return std::hash<string>{}(k.name); }
};

int main(){
 // unordered_map<const Entity, bitset<24>, KeyHasher> m1; // 正常编译
 unordered_map<const Entity, bitset<24>> m2; // 编译报错:unordered_map构造函数非法
  return 0;
}

错误信息

<source>: In function 'int main()':
<source>:25:43: error: use of deleted function 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() 
[with _Key = const Entity; _Tp = std::bitset<24>; _Hash = std::hash<const Entity>; _Pred = std::equal_to<const Entity>; _Alloc = std::allocator<std::pair<const Entity, std::bitset<24> > >]'
   25 |   unordered_map<const Entity, bitset<24>> m2;
      |                                           ^~
In file included from /opt/compiler-explorer/gcc-cxx-modules-trunk-20220427/include/c++/11.0.0/unordered_map:47,
                 from <source>:3:
/opt/compiler-explorer/gcc-cxx-modules-trunk-20220427/include/c++/11.0.0/bits/unordered_map.h:141:7: note: 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = const Entity; _Tp = std::bitset<24>; _Hash = std::hash<const Entity>; _Pred = std::equal_to<const Entity>; _Alloc = std::allocator<std::pair<const Entity, std::bitset<24> > >]'
 is implicitly deleted because the default definition would be ill-formed:
  141 |       unordered_map() = default;

问题原因与解决方法

核心原因

std::unordered_map默认使用的哈希器是std::hash<Key>模板,而非你在Entity内部重载的operator()。你在Entity中重载的operator()只是让Entity本身成为一个函数对象,但这和标准库要求的std::hash特化完全是两回事。

当你声明unordered_map<const Entity, ...>时,编译器会尝试实例化std::hash<const Entity>,但标准库并未为你的自定义类型提供这个特化版本,导致哈希器类型无效,进而使得unordered_map的默认构造函数被隐式删除,最终编译报错。

而使用KeyHasher时,你显式指定了哈希器类型,unordered_map会直接调用KeyHasher的operator()计算哈希,因此可以正常编译。

解决方法

方法1:显式指定哈希器为Entity类型

既然Entity本身是合法的函数对象,你可以直接将它作为unordered_map的哈希器模板参数:

unordered_map<const Entity, bitset<24>, Entity> m2;

方法2:特化std::hash<Entity>

为你的自定义类型特化标准库的std::hash模板,这样unordered_map就能自动识别并使用你的哈希逻辑:

namespace std {
    template<>
    struct hash<Entity> {
        size_t operator()(const Entity& k) const noexcept {
            return hash<string>{}(k.name);
        }
    };
}

添加这段特化代码后,原本的unordered_map<const Entity, bitset<24>> m2;就能正常编译运行。

补充说明

你在Entity内部重载的operator()本身没有语法错误,它可以作为普通函数对象使用,但不符合std::unordered_map默认哈希器的查找规则。默认情况下,unordered_map只会优先使用std::hash<Key>的特化,或者你显式传入的哈希器类型。

内容的提问来源于stack exchange,提问作者ExpertNoob1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:15:34