C++20中std::unordered_map自定义小写比较编译错误C2064求助
问题:C++20中带大小写不敏感键的unordered_map编译失败(error C2064)
问题场景
尝试创建键为std::wstring、值为std::pair<int, int>的std::unordered_map,要求按键的小写形式进行比较,但编译时触发error C2064,提示“项不会计算为接受1个参数的函数”。
错误原因
你搞混了std::unordered_map的模板参数顺序:
- 第三个模板参数是哈希函数(需要接收单个键值,返回
size_t类型的哈希值) - 第四个模板参数才是相等比较器(接收两个键值,返回
bool表示是否相等)
你的代码把作为相等比较器的CmpByWStringEquality放到了哈希函数的位置,而这个结构体只实现了接收两个参数的operator(),没有实现哈希函数要求的单参数调用操作符,因此编译器报错。
修复方案
- 编写大小写不敏感的哈希函数:将输入的
std::wstring转小写后,使用标准库的std::hash<std::wstring>生成哈希值 - 保留并优化相等比较器:优化为直接逐个字符比较转小写后的结果,避免生成临时字符串的开销
- 正确指定unordered_map的模板参数:哈希函数放第三个位置,相等比较器放第四个位置
修复后的完整代码
#include <algorithm> #include <cctype> #include <locale> #include <string> #include <iostream> #include <unordered_map> std::wstring FOREX1 = L"BTCUSD"; std::wstring FOREX2 = L"BTCUSD"; // 大小写不敏感的相等比较器 struct CaseInsensitiveWStringEqual { bool operator()(const std::wstring& a, const std::wstring& b) const { if (a.size() != b.size()) return false; // 逐个字符转小写后比较,避免生成临时字符串 return std::equal(a.begin(), a.end(), b.begin(), [](wchar_t c1, wchar_t c2) { return ::towlower(c1) == ::towlower(c2); }); } }; // 大小写不敏感的哈希函数 struct CaseInsensitiveWStringHash { size_t operator()(const std::wstring& s) const { std::wstring lower_s(s); std::transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::towlower); return std::hash<std::wstring>()(lower_s); } }; struct PatternMatcher { std::wstring inputValue; explicit PatternMatcher(std::wstring a_inputValue) : inputValue(std::move(a_inputValue)) {} static void thirdFunction(std::unordered_map<std::wstring, std::pair<int, int>, CaseInsensitiveWStringHash, CaseInsensitiveWStringEqual>& m_symbol_spreads_map) { m_symbol_spreads_map.insert(std::make_pair(FOREX2, std::make_pair(-1, 3))); } static void secondFunction(std::unordered_map<std::wstring, std::pair<int, int>, CaseInsensitiveWStringHash, CaseInsensitiveWStringEqual>& m_symbol_spreads_map) { if (m_symbol_spreads_map.find(FOREX1) == m_symbol_spreads_map.end()) { thirdFunction(m_symbol_spreads_map); } double bid_spread = m_symbol_spreads_map.at(FOREX1).first; double ask_spread = m_symbol_spreads_map.at(FOREX1).second; std::cout << "Bid spread: " << bid_spread << std::endl; std::cout << "Ask spread: " << ask_spread << std::endl; } static void firstFunction() { std::unordered_map<std::wstring, std::pair<int, int>, CaseInsensitiveWStringHash, CaseInsensitiveWStringEqual> m_symbol_spreads_map = {}; secondFunction(m_symbol_spreads_map); std::cout << "Symbol spread map size: " << m_symbol_spreads_map.size() << std::endl; std::cout << m_symbol_spreads_map.at(FOREX1).first << std::endl; std::cout << m_symbol_spreads_map.at(FOREX1).second << std::endl; } }; // 测试入口 int main() { PatternMatcher::firstFunction(); return 0; }
额外说明
- 关于
::towlower:如果需要处理非ASCII字符(如Unicode中的特殊字母),建议结合std::locale使用,例如std::use_facet<std::ctype<wchar_t>>(std::locale()).tolower(c) - 哈希函数的优化:如果不想每次生成临时小写字符串,可以实现一个直接计算原字符串小写形式哈希值的逻辑,减少内存分配
内容的提问来源于stack exchange,提问作者Sahib Yar
相关产品推荐
相关产品推荐

