无需显式定义哈希与==,能否让RouterID作为unordered_map的键?
问题解决:无需修改IPv4类让unordered_map正常工作
首先修正你代码里的两处基础问题:
- IPv4类的转换运算符返回了未定义的
octets,应该改为成员变量octets_; - 转换运算符未加
const修饰,无法对const对象执行转换,而unordered_map的操作会默认处理const键,这会触发编译错误。
修正后的IPv4类代码:
class IPv4 { uint32_t octets_; public: operator uint32_t() const { return octets_; } // 修正变量名并添加const }; struct RouterID : public IPv4 {};
接下来可以无需在IPv4类内部显式定义哈希函数或operator==,通过为unordered_map指定外部的哈希和比较器来解决问题:
方法1:自定义仿函数作为哈希与比较器
利用IPv4的隐式转换特性,将RouterID转为uint32_t后,复用标准库对uint32_t的哈希和相等实现:
#include <functional> #include <unordered_map> #include <string> // 哈希函数:将RouterID转为uint32_t后计算哈希 struct RouterIDHash { size_t operator()(const RouterID& rid) const { return std::hash<uint32_t>{}(static_cast<uint32_t>(rid)); } }; // 相等比较:将RouterID转为uint32_t后比较值 struct RouterIDEqual { bool operator()(const RouterID& lhs, const RouterID& rhs) const { return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs); } }; // 声明unordered_map时指定哈希和比较器 std::unordered_map<RouterID, std::string, RouterIDHash, RouterIDEqual> routers;
方法2:C++20+ 简洁写法(使用lambda)
如果使用C++20及以上标准,可以直接用lambda作为模板参数,无需单独定义仿函数:
#include <functional> #include <unordered_map> #include <string> constexpr auto routerHash = [](const RouterID& rid) { return std::hash<uint32_t>{}(static_cast<uint32_t>(rid)); }; constexpr auto routerEqual = [](const RouterID& lhs, const RouterID& rhs) { return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs); }; // 初始化时传入lambda实例 std::unordered_map<RouterID, std::string, decltype(routerHash), decltype(routerEqual)> routers(10, routerHash, routerEqual);
以上两种方式都没有修改IPv4类的内部实现,完全依赖其隐式转换特性,即可让unordered_map正常工作。
内容的提问来源于stack exchange,提问作者razenkovv
相关产品推荐
相关产品推荐

