C++声明std::map<LoggedUser, GameData>触发C2676<运算符未定义错误
编译错误根因
std::map是基于红黑树实现的有序关联容器,默认使用std::less<T>作为键比较规则,要求作为键的类型必须支持const上下文下的小于比较操作,用于完成键的排序、重复校验和查找逻辑。
你的代码中使用LoggedUser作为std::map的键类型,但该类未定义符合要求的operator<重载,因此触发C2676编译错误。
修复方法
二选一即可,推荐优先用方案1,代码更简洁。
方案1:为LoggedUser重载const限定的小于运算符
修改LoggedUser.h代码,补充小于运算符重载,同时给getter方法加const限定(const对象无法调用非const成员方法):
#pragma once #include <string> class LoggedUser { private: std::string _m_username; int id; public: LoggedUser(); LoggedUser(std::string username, int id); // 给getter加const后缀,允许const对象调用 std::string get_username() const; int get_id() const; // 重载小于运算符,参数为const引用,加友元访问私有成员 friend bool operator<(const LoggedUser& lhs, const LoggedUser& rhs) { // 比较逻辑:先比对用户名,用户名一致时比对id,保证键唯一性 if (lhs._m_username != rhs._m_username) { return lhs._m_username < rhs._m_username; } return lhs.id < rhs.id; } };
对应cpp实现里,get_username和get_id的定义也要同步加const后缀:
std::string LoggedUser::get_username() const { return _m_username; } int LoggedUser::get_id() const { return id; }
方案2:自定义map比较器,不修改LoggedUser类
如果不想侵入修改LoggedUser类,可以自定义比较仿函数,在声明map时作为第三个模板参数传入。
首先在Game.h中声明map前定义比较结构体:
struct LoggedUserCmp { // 比较运算符必须加const后缀 bool operator()(const LoggedUser& lhs, const LoggedUser& rhs) const { if (lhs.get_username() != rhs.get_username()) { return lhs.get_username() < rhs.get_username(); } return lhs.get_id() < rhs.get_id(); } };
再将原map声明修改为:
std::map<LoggedUser, GameData, LoggedUserCmp> m_players;
注意:该方案同样需要给LoggedUser的两个getter方法加const后缀,否则const引用的LoggedUser对象无法调用非const方法,编译依然会报错。
注意事项
- 重载的比较逻辑必须满足严格弱序规则:即对任意a、b,不能同时出现
a < b和b < a为真的情况,否则会导致map插入、查找时出现未定义行为。 - 所有用于比较的方法/运算符必须带const限定,否则map内部持有的const键对象无法调用对应方法,会继续报相同的C2676错误。
内容的提问来源于stack exchange,提问作者Tomer Cher
相关产品推荐
相关产品推荐

