如何将存在值重复的enum class作为map的唯一键?
解决枚举类成员值重复时作为map唯一键的问题
std::map默认用std::less<T>比较键,枚举类的比较逻辑基于底层整数值,所以值相同的成员会被视为同一键。要让每个枚举成员(无论值是否重复)都作为唯一键存储,有以下几种可行方案:
方案一:自定义比较器适配std::map
自定义比较器,给每个枚举成员分配唯一标识,通过比较标识区分不同成员。
示例代码:
#include <map> #include <vector> enum class SomeEnum { A = 1, B = 2, C = 2 }; struct EnumUniqueComparator { bool operator()(SomeEnum lhs, SomeEnum rhs) const { auto get_unique_id = [](SomeEnum e) { switch(e) { case SomeEnum::A: return 0; case SomeEnum::B: return 1; case SomeEnum::C: return 2; default: return -1; } }; return get_unique_id(lhs) < get_unique_id(rhs); } }; int main() { std::map<SomeEnum, std::vector<int>, EnumUniqueComparator> my_map; my_map[SomeEnum::A].push_back(10); my_map[SomeEnum::B].push_back(20); my_map[SomeEnum::C].push_back(30); // 三个枚举成员会被作为独立键存储 return 0; }
如果枚举成员较多,可用宏简化ID分配:
#define ENUM_ID_MAPPING(ENUM) case SomeEnum::ENUM: return __COUNTER__; struct EnumUniqueComparator { bool operator()(SomeEnum lhs, SomeEnum rhs) const { auto get_unique_id = [](SomeEnum e) { switch(e) { ENUM_ID_MAPPING(A) ENUM_ID_MAPPING(B) ENUM_ID_MAPPING(C) default: return -1; } }; return get_unique_id(lhs) < get_unique_id(rhs); } };
__COUNTER__是编译器内置宏,每次调用自动生成递增的唯一整数,新增枚举成员时只需添加一行ENUM_ID_MAPPING(成员名)即可。
方案二:自定义哈希与相等判断适配std::unordered_map
如果偏好无序哈希表,可给std::unordered_map自定义哈希函数和相等判断规则,同样基于枚举成员的唯一标识。
示例代码:
#include <unordered_map> #include <vector> #include <functional> enum class SomeEnum { A = 1, B = 2, C = 2 }; struct EnumUniqueHash { size_t operator()(SomeEnum e) const { switch(e) { case SomeEnum::A: return 0; case SomeEnum::B: return 1; case SomeEnum::C: return 2; default: return std::hash<int>()(-1); } } }; struct EnumUniqueEqual { bool operator()(SomeEnum lhs, SomeEnum rhs) const { return EnumUniqueHash{}(lhs) == EnumUniqueHash{}(rhs); } }; int main() { std::unordered_map<SomeEnum, std::vector<int>, EnumUniqueHash, EnumUniqueEqual> my_umap; my_umap[SomeEnum::A].push_back(10); my_umap[SomeEnum::B].push_back(20); my_umap[SomeEnum::C].push_back(30); return 0; }
备选方案:修改枚举定义(若允许)
如果可以修改原枚举的定义,直接给每个成员分配唯一的底层值,就能直接使用默认的map容器,无需额外适配:
enum class SomeEnum { A = 1, B = 2, C = 3 // 改为唯一值 }; // 直接使用默认std::map即可 std::map<SomeEnum, std::vector<int>> my_map;
内容的提问来源于stack exchange,提问作者steep
相关产品推荐
相关产品推荐

