以下是std::lower_bound
&的示例示例。 std::upper_bound
,注意比较lambda传递给他们的签名 -
const auto lower_x = std::lower_bound(
points.begin(), points.end(), rec.min_corner.x,
[](const RankedPoint &rp, const double x) { return rp.point.x < x; });
const auto upper_x = std::upper_bound(
points.begin(), points.end(), rec.max_corner.x,
[](const double x, const RankedPoint &rp) { return x < rp.point.x; });
保持签名完全相反的可能原因是什么?当我使用auto
而不是带有错误签名的明确类型时,我并没有意识到这一点并且gcc编译了(clang并没有)。花了我10分钟的挫折感。
答案 0 :(得分:4)
自定义比较器版本lower_bound
和upper_bound
是简单使用<
的概括。 lower_bound
产生的第一个元素不小于value
,因此发生的检查是elem < value
(或!(elem < value)
真的)。 upper_bound
产生第一个元素更大而不是value
,但我们不是编写elem > value
(这需要operator>
),而是翻转排序到value < elem
。这保持了operator<
的唯一要求,但结果是,参数的顺序是相反的。
这从elem < value
到comp(elem, value)
和value < elem
推广到comp(value, elem)
。
最终,在设计时我们可以做出两种选择:我们可以在任何地方使用相同的比较器,但对于某些算法,参数的顺序是相反的。或者,我们可以为每个算法使用不同的比较器,具体取决于对特定算法有意义的。在任何地方使用相同的比较器都有很多优点 - 你只需使用相同的比较器:
std::vector<int> vs = ...;
std::sort(vs.begin(), vs.end(), std::greater<>{});
auto lo = std::lower_bound(vs.begin(), vs.end(), 5, std::greater<>{});
auto hi = std::upper_bound(vs.begin(), vs.end(), 5, std::greater<>{});
到处都是相同的比较器,代码看起来正确,并做正确的事情。如果我们将upper_bound()
传递给其比较器的参数的顺序翻转,我们必须传入std::less<>{}
。哪个只是......看起来不对劲。
你可能会对Ranges TS感兴趣,它通过可调用的投影来解决这个问题。