如何存储带有不同比较器的std::map对象引用?
最优实现方案
由于std::map<int, int, std::greater<int>>和std::map<int, int, std::less<int>>是不同的具体类型,无法直接用单一类型的引用存储,推荐以下两种高效且符合你需求的实现方式:
方案一:使用std::variant(C++17及以上,推荐)
std::variant是类型安全的联合体,可以存储指定类型的引用(通过std::reference_wrapper包装),开销极低,能无缝对接现有使用std::greater/std::less的代码,完全适配你的场景。
示例代码:
#include <map> #include <variant> #include <functional> // 用于std::reference_wrapper // 定义可存储两种map引用的variant类型 using MapRefVariant = std::variant< std::reference_wrapper<std::map<int, int, std::less<int>>>, std::reference_wrapper<std::map<int, int, std::greater<int>>> >; // 处理map的示例函数 void process_map(MapRefVariant map_ref) { // 通过std::visit分发处理两种类型的map std::visit([](auto&& wrapped_map) { auto& map = wrapped_map.get(); // 这里直接操作map,比如遍历或修改 for (const auto& [key, val] : map) { // 执行业务逻辑 } }, map_ref); } int main() { std::map<int, int, std::less<int>> less_map = {{1,2}, {3,4}}; std::map<int, int, std::greater<int>> greater_map = {{5,6}, {7,8}}; MapRefVariant ref1 = std::ref(less_map); MapRefVariant ref2 = std::ref(greater_map); process_map(ref1); process_map(ref2); return 0; }
方案二:抽象基类+模板包装器(兼容C++11及以上)
如果项目使用较旧的C++标准,可通过抽象基类定义统一操作接口,再用模板子类包装不同类型的map,通过基类指针/引用实现统一存储。这种方式兼容性更好,但需要提前定义好所需的操作接口。
示例代码:
#include <map> #include <memory> // 抽象基类,定义map的统一操作接口 class BaseMap { public: virtual ~BaseMap() = default; // 示例接口:根据键获取值 virtual int get_value(int key) const = 0; // 可根据需求添加插入、遍历等更多接口 }; // 模板子类,包装具体的map类型 template <typename Cmp> class MapWrapper : public BaseMap { public: MapWrapper(std::map<int, int, Cmp>& map) : map_ref_(map) {} int get_value(int key) const override { auto it = map_ref_.find(key); return it != map_ref_.end() ? it->second : -1; // 示例默认值 } private: std::map<int, int, Cmp>& map_ref_; }; // 使用示例 int main() { std::map<int, int, std::less<int>> less_map = {{1,2}, {3,4}}; std::map<int, int, std::greater<int>> greater_map = {{5,6}, {7,8}}; std::unique_ptr<BaseMap> wrapper1 = std::make_unique<MapWrapper<std::less<int>>>(less_map); std::unique_ptr<BaseMap> wrapper2 = std::make_unique<MapWrapper<std::greater<int>>>(greater_map); // 通过基类指针调用统一接口 wrapper1->get_value(1); // 返回2 wrapper2->get_value(5); // 返回6 return 0; }
方案选择建议
- 若使用C++17及以上,优先选方案一:
std::variant类型安全、开销极小,无需额外定义接口,完全适配你与现有代码集成的需求,且不会引入自定义比较器的性能问题。 - 若需兼容旧标准,再考虑方案二,但需提前明确所有需要的操作接口。
内容的提问来源于stack exchange,提问作者Alexander Richter
相关产品推荐
相关产品推荐

