如何无需显式指定比较器即可用std::set存储自定义类?
无需显式指定比较器使用std::set的方法
当然可以,有两种常用方案能让你直接以std::set<MyType>的形式声明集合,核心是让std::set默认依赖的std::less<MyType>能正确比较你的自定义类:
1. 给自定义类添加成员operator<
这是最直观且推荐的方式,因为std::less默认会优先调用类型的成员operator<来实现比较逻辑。示例代码:
class MyInt { private: int val; public: MyInt(int v) : val(v) {} // 定义成员operator<,指定类的比较规则 bool operator<(const MyInt& other) const { return this->val < other.val; } }; // 直接使用std::set<MyInt>,无需额外指定比较器 std::set<MyInt> mySet; mySet.insert(MyInt(5)); mySet.insert(MyInt(2));
这种方式把比较逻辑和类本身绑定,代码可读性高,符合C++的惯用设计思路。
2. 在std命名空间特化std::less
如果无法修改自定义类的代码(比如类来自第三方库),可以像你给std::hash做特化那样,对std::less进行特化。示例代码:
class MyInt { private: int val; public: MyInt(int v) : val(v) {} // 假设无法修改类内部代码,只能通过公共接口访问数据 int getVal() const { return val; } }; namespace std { template<> struct less<MyInt> { bool operator()(const MyInt& a, const MyInt& b) const { return a.getVal() < b.getVal(); } }; } // 同样可以直接使用std::set<MyInt> std::set<MyInt> mySet; mySet.insert(MyInt(5)); mySet.insert(MyInt(2));
这种方案和你处理std::unordered_map哈希函数的思路完全一致,适合无法修改类源码的场景。
注意:不推荐全局重载非成员的
operator<,这种方式可能在命名空间查找时引发意外冲突,尤其是当类属于自定义命名空间时,参数依赖查找(ADL)的行为不如成员函数或std::less特化稳定。
内容的提问来源于stack exchange,提问作者rare77
相关产品推荐
相关产品推荐

