如何在C++自定义类中使用std::unordered_set::contains()?
解决std::unordered_set自定义类元素调用contains(const char*)的编译错误
问题原因
std::unordered_set的contains成员函数默认仅接受与元素类型完全匹配的参数。要实现异构查找(即用非元素类型参数查找,比如用const char*查找MyClass元素),必须满足两个核心条件:
- 哈希仿函数(Hash)和相等仿函数(Equal)已实现对应异构类型的重载(你已完成这一步)
- 哈希仿函数和相等仿函数中必须定义
is_transparent类型,显式告知编译器支持透明查找——这是你代码中缺失的关键部分。
C++标准明确规定:只有当哈希和相等仿函数都包含is_transparent定义时,unordered_set才会启用支持异构参数的contains重载版本。否则编译器只会寻找接受MyClass类型参数的contains函数,最终导致编译失败。
至于std::string作为元素时能正常运行,是因为标准库的std::hash<std::string>和std::equal_to<std::string>在C++14及以后版本中已内置is_transparent定义,天然支持异构查找。
解决方法
在MyClass::Hash和MyClass::Equal结构体中添加is_transparent类型定义即可:
修改后的MyClass关键代码片段:
// Hash functor struct Hash { using is_transparent = void; // 添加透明查找标记 std::size_t operator()(const MyClass &class_) const { return std::hash<std::string>()(class_.m_name); } std::size_t operator()(const std::string &name) const { return std::hash<std::string>()(name); } std::size_t operator()(const char* name) const { return std::hash<std::string>()(name); } }; // Equal functor struct Equal { using is_transparent = void; // 添加透明查找标记 bool operator()(const MyClass &lhs, const MyClass &rhs) const { return lhs.m_name == rhs.m_name; } bool operator()(const MyClass &lhs, const std::string &rhs) const { return lhs.m_name == rhs; } bool operator()(const std::string &lhs, const MyClass &rhs) const { return lhs == rhs.m_name; } bool operator()(const MyClass &lhs, const char* rhs) const { return lhs.m_name == rhs; } bool operator()(const char* lhs, const MyClass &rhs) const { return lhs == rhs.m_name; } };
验证修改
添加is_transparent标记后,编译器会识别到unordered_set支持异构查找,set.contains("key1")会自动匹配你实现的哈希和相等重载逻辑,无需构造临时MyClass对象,编译即可通过并正常运行。
内容的提问来源于stack exchange,提问作者Dzious
相关产品推荐
相关产品推荐

