网站建站 在线制作,wordpress 图片菜单,正版win10做win7系统下载网站,济南网站建设公司官网文章目录unordered_map使用MFC的CString作为键值遇到C2056和C2064错误问题出现的背景解决方案总结unordered_map使用MFC的CString作为键值遇到C2056和C2064错误
问题出现的背景
在我的一个老工程项目中#xff0c;使用C的std::unordered_map时#xff0c;使用了MFC的CStrin…
文章目录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_castLPCTSTR(str));}
};代码是VS2015环境下实现的然后当项目代码升级迁移到VS2022时随着VC版本的升级hash_value这种非标准函数不再可用参考unordered_map使用std::string作为键的办法示例代码如下
#include iostream
#include string
#include unordered_mapint main()
{std::unordered_mapstd::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_mapstd::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::hashstd::string不需要额外定义哈希函数。 然而我们将这种思路放到CString上时直接使用std::hashCString会导致编译错误C2056和C2064因为标准库并没有为MFC的CString提供默认的哈希函数和比较操作符。 解决方案
为了解决这个问题我们需要为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 StringTraitssize_t operator()(const CStringTBaseType, StringTraits _Keyval) const noexcept{ // hash _Keyval to size_t value by pseudorandomizing transformreturn std::_Hash_array_representation(_Keyval.GetString(), _Keyval.GetLength());}
};// 应用示例
unordered_mapCString, int, CStringHasher, CStrCmp m_filemap;
unordered_mapCString, int, CStringHasher, CStrCmp::const_iterator itr m_filemap.find(filename);在上述代码中我们定义了两个结构体
CStrCmp用于比较两个CString对象是否相等重载了operator()。CStringHasher用于计算CString的哈希值重载了operator()利用了CStringT的成员函数GetString()和GetLength()来获取字符串内容和长度并调用了标准库的哈希函数。
当然我们也可以在namespace stdstd命名空间中定义这哈希和比较运算事实上这种情况下我们只需要定义哈希因为这种模式下会默认使用CString自带的比较运算
namespace std
{template typename BaseType, class StringTraitsstruct hashCStringTBaseType, StringTraits{ // hash functor for CStringTBaseType, StringTraitssize_t operator()(const CStringTBaseType, StringTraits _Keyval) const noexcept{ // hash _Keyval to size_t value by pseudorandomizing transformreturn (_Hash_array_representation(_Keyval.GetString(), _Keyval.GetLength()));}};
} // namespace std调用示例代码如下
std::unordered_mapCString, int myMap { {Lacad.lsp, 1}, {Lacaddoc.lsp, 1}, {Lacad.mnl, 2} };
std::unordered_mapCString, int::const_iterator it myMap.find(Lacad.lsp);该代码编译和执行均正常。
总结
通过为MFC的CString自定义哈希函数和比较操作符我们成功解决了在使用std::unordered_map时遇到的编译错误C2056和C2064的问题。这种方法不仅适用于CString也可以推广到其他自定义类型只要为它们提供合适的哈希函数和比较操作符即可。这样我们就能充分利用unordered_map的高效查找性能同时避免编译错误。 然而CString类不是线程安全的。在多线程环境中如果多个线程同时操作同一个 CString实例例如作为 unordered_map的键并进行修改可能会导致内存地址错误或进程异常退出。