当前位置: 首页 > news >正文

unordered_map使用MFC的CString作为键值遇到C2056和C2064错误

文章目录

  • unordered_map使用MFC的CString作为键值遇到C2056和C2064错误
    • 问题出现的背景
    • 解决方案
    • 总结

unordered_map使用MFC的CString作为键值遇到C2056和C2064错误

问题出现的背景

在我的一个老工程项目中,使用C++的std::unordered_map时,使用了MFC的CString作为键值类型,遇到编译错误C2056和C2064。这些错误通常与哈希函数和比较操作符的缺失有关。

此前,项目使用了如下代码实现CString的哈希函数和比较操作符:

// CString 哈希函数结构体,用于unordered_map
struct CStrHashFunc
{size_t operator()(const CString &str) const{return hash_value(static_cast<LPCTSTR>(str));}
};

代码是VS2015环境下实现的,然后当项目代码升级迁移到VS2022时,随着VC++版本的升级,hash_value这种非标准函数不再可用,参考unordered_map使用std::string作为键的办法,示例代码如下:

#include <iostream>
#include <string>
#include <unordered_map>int main()
{std::unordered_map<std::string, double> mymap = {{"mom",5.4},{"dad",6.1},{"bro",5.9},{"姐姐",5.5 }};std::string input;std::cout << "who? ";getline(std::cin, input);std::unordered_map<std::string, double>::const_iterator got = mymap.find(input);if (got == mymap.end())std::cout << "not found";elsestd::cout << got->first << " is " << got->second;std::cout << std::endl;return 0;
}

上述代码以unordered_map的查找为例,使用了std::string作为键值类型,并且可以直接使用std::hash<std::string>,不需要额外定义哈希函数。
然而,我们将这种思路放到CString上时,直接使用std::hash<CString>会导致编译错误C2056和C2064,因为标准库并没有为MFC的CString提供默认的哈希函数和比较操作符。

error

解决方案

为了解决这个问题,我们需要为CString自定义哈希函数和比较操作符。以下是一个示例代码,展示了如何实现这一点,该代码可以在VS2022中编译通过,且功能正常:

// CString 比较函数结构体,用于unordered_map
struct CStrCmp
{bool operator()(const CString &str1, const CString &str2) const{return str1 == str2;}
};// CString 哈希函数结构体,用于unordered_map
struct CStringHasher
{template <typename BaseType, class StringTraits>size_t operator()(const CStringT<BaseType, StringTraits>& _Keyval) const noexcept{ // hash _Keyval to size_t value by pseudorandomizing transformreturn std::_Hash_array_representation(_Keyval.GetString(), _Keyval.GetLength());}
};// 应用示例:
unordered_map<CString, int, CStringHasher, CStrCmp> m_filemap;
unordered_map<CString, int, CStringHasher, CStrCmp>::const_iterator itr = m_filemap.find(filename);

在上述代码中,我们定义了两个结构体:

  1. CStrCmp:用于比较两个CString对象是否相等,重载了operator()
  2. CStringHasher:用于计算CString的哈希值,重载了operator(),利用了CStringT的成员函数GetString()GetLength()来获取字符串内容和长度,并调用了标准库的哈希函数。

当然,我们也可以在namespace std(std命名空间)中定义这哈希和比较运算(事实上这种情况下我们只需要定义哈希,因为这种模式下会默认使用CString自带的比较运算):

namespace std
{template <typename BaseType, class StringTraits>struct hash<CStringT<BaseType, StringTraits>>{ // hash functor for CStringT<BaseType, StringTraits>size_t operator()(const CStringT<BaseType, StringTraits>& _Keyval) const noexcept{ // hash _Keyval to size_t value by pseudorandomizing transformreturn (_Hash_array_representation(_Keyval.GetString(), _Keyval.GetLength()));}};
} // namespace std

调用示例代码如下:

std::unordered_map<CString, int> myMap = { {L"acad.lsp", 1}, {L"acaddoc.lsp", 1}, {L"acad.mnl", 2} };
std::unordered_map<CString, int>::const_iterator it = myMap.find(L"acad.lsp");

该代码编译和执行均正常。

总结

通过为MFC的CString自定义哈希函数和比较操作符,我们成功解决了在使用std::unordered_map时遇到的编译错误C2056和C2064的问题。这种方法不仅适用于CString,也可以推广到其他自定义类型,只要为它们提供合适的哈希函数和比较操作符即可。这样,我们就能充分利用unordered_map的高效查找性能,同时避免编译错误。
然而,CString类​​不是线程安全​​的。在多线程环境中,如果多个线程同时操作​​同一个​​ CString实例(例如作为 unordered_map的键并进行修改),可能会导致内存地址错误或进程异常退出。


文章转载自:

http://CeiSQCQI.bpmfz.cn
http://HwNtdDdJ.bpmfz.cn
http://Q8d9pjOm.bpmfz.cn
http://tX8pKtS9.bpmfz.cn
http://oo069Hai.bpmfz.cn
http://NVBItSFh.bpmfz.cn
http://7bEpgZvl.bpmfz.cn
http://jddkddgV.bpmfz.cn
http://2Z75pKry.bpmfz.cn
http://2rrYEHbd.bpmfz.cn
http://sHrAaqkY.bpmfz.cn
http://M8mccS5v.bpmfz.cn
http://8YlDyG1L.bpmfz.cn
http://iCAKo9UZ.bpmfz.cn
http://8qE2lIPF.bpmfz.cn
http://RSYBefo9.bpmfz.cn
http://7WbaTTGa.bpmfz.cn
http://QbpXPTvc.bpmfz.cn
http://64MTDOR8.bpmfz.cn
http://bLmmOHNo.bpmfz.cn
http://42Qs6alB.bpmfz.cn
http://s38EtX6z.bpmfz.cn
http://zxoiLn7A.bpmfz.cn
http://9xelrErh.bpmfz.cn
http://OqbRibYE.bpmfz.cn
http://9UFCi1yu.bpmfz.cn
http://aUSPfRzh.bpmfz.cn
http://gRYXcHjX.bpmfz.cn
http://pdrlGoOs.bpmfz.cn
http://fFOUK5jS.bpmfz.cn
http://www.dtcms.com/a/383633.html

相关文章:

  • MFC_Install_Create
  • 大数据知识框架思维导图(构造知识学习框架)
  • Spring Boot 集成第三方 API 时,常见的超时与重试机制设计
  • 设计模式——创建型模式
  • Nginx_Tomcat综合案例
  • Java常见类类型与区别详解:从实体类到异常类的全面指南
  • MOS管驱动栅极出现振铃现象
  • camke中采用vcpkg工具链设置OSG时
  • 玩转ElasticSearch
  • 设计模式-模板模式详解
  • GDB调试技巧实战--揪出内存泄漏元凶
  • LLM基础-工程化
  • Ubuntu系统下交叉编译Android的Lame库
  • AI 重构医疗:辅助诊断、药物研发、健康管理的三大落地场景实践
  • MySQL的日志系统(redolog、binlog、WAL技术)
  • 贪心算法应用:半导体晶圆生产问题详解
  • 按键精灵解决重复性点击
  • 索引-分类
  • webrtc弱网-IntervalBudget类源码分析与算法原理
  • 第20课:数据治理与合规
  • 模型训练中的数据泄露:原理解析与实战防范指南
  • 凌晨0-3点不睡,你熬的不是夜,是人生!
  • [哈希表]966. 元音拼写检查器
  • 密码库的轻量化定制裁剪:技术原理与实践指南
  • Tomcat vs JBoss:轻量级与重型Java服务器对比
  • v-model与-sync的演变和融合
  • Vue的快速入门
  • 26考研——进程与线程(2)
  • Java基础 9.14
  • Node.js核心模块介绍