【发布时间】:2018-09-05 18:23:18
【问题描述】:
我经常发现自己想为 struct 或 class 创建一个比较器对象,它只是提取类的一个成员,并对其进行通常的 < 比较。
例如:
struct student {
int id;
std::string name;
};
// sort by ID
std::sort(students.begin(), students.end(), [](const student& l, const student& r){ return l.id < r.id; });
那里有很多样板,特别是因为我们必须重复 l 和 r 的声明。标准库中是否有一种方法可以创建基于“提取器”函数的比较器,该函数返回要比较的对象?
类似:
std::sort(students.begin(), students.end(), compare_on([](const student& s){ return s.id; });
我正在使用 C++11,但我也对后续标准中不适用于 C++11 的解决方案感兴趣(因此我可以在我的“升级原因”列表中添加一些内容)。
我在这里询问有关使用单个成员作为 comprand 的问题,以及默认比较“小于”,但对于易于组合的技术的奖励积分,例如允许您按字典顺序使用两个字段,或更改比较运算符。
【问题讨论】:
-
我听说过这个案例的一个术语是projection(看起来像
sort(students.begin(), students.end(), &student::id))。标准库不支持 -
使用 C++14,您可以通过将
[](const student& l, const student& r)更改为[](const auto& l, const auto& r)来稍微减轻痛苦。 -
@JesperJuhl - 是的,好点,它减少了声明样板,但它并没有摆脱我看到的主要问题:你仍然需要声明左右,并实现自己比较逻辑。由于比较函数的参数通常是对称的,所以第一个似乎是多余的。当它只是
l.f < r.f时,自己实现“逻辑”并不算太糟糕,但考虑一下如果你想在两个字段上进行比较,那么你就会写一些像l.f1 < r.f1 || (l.f1 == r.f1 && l.f2 < r.f2)这样的可憎的东西。 -
@BeeOnRope 我并没有试图解决整个问题。只是简单的一点;-)
-
@BeeOnRope:
std::tie可能对几个成员有帮助:return std::tie(l.f1, l.f2) < std::tie(r.f1, r.f2);,您甚至可以编写 lambda/functionas_tuple以避免重复.f1, .f2。
标签: c++ c++11 comparison