You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(),没有实现哈希函数要求的单参数调用操作符,因此编译器报错。

修复方案

  1. 编写大小写不敏感的哈希函数:将输入的std::wstring转小写后,使用标准库的std::hash<std::wstring>生成哈希值
  2. 保留并优化相等比较器:优化为直接逐个字符比较转小写后的结果,避免生成临时字符串的开销
  3. 正确指定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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:50:52