std :: upper_bound和std :: lower_bound的不同比较签名

Abh*_*yal 6 c++ stl c++-standard-library c++11 c++14

以下是两个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; });
Run Code Online (Sandbox Code Playgroud)

保持签名完全相反的可能原因是什么?当我用auto而不是带有错误签名的明确类型时,我没有意识到这一点和gcc编译(clang没有).耗费了我10分钟的挫折感.

Bar*_*rry 5

的习俗比较版本lower_boundupper_bound是简单地使用的概括<lower_bound产生不小于 的第一个元素value,因此发生的检查是elem < value(或!(elem < value)真的)。upper_bound得到的第一个元素更大的value,但我们的,而不是写elem > value(这可能需要operator>),我们只是翻转顺序来value < elem。这保持了 的唯一要求operator<,但结果是参数的顺序颠倒了。

这概括了elem < valuetocomp(elem, value)value < elemto 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<>{});
Run Code Online (Sandbox Code Playgroud)

到处都是相同的比较器,代码看起来正确,并且做正确的事情。如果我们颠倒upper_bound()传递给它的比较器的参数的顺序,我们就必须传入std::less<>{}. 这只会……看起来不对。


您可能会对Ranges TS感兴趣,它通过可调用的投影解决了这个问题。