Custom versions of the comparator lower_bound and upper_bound are generalizations of the simple use of < . lower_bound gives the first element that is not less than value , so the check is done elem < value (or !(elem < value) really). upper_bound gives the first element greater than value , but instead of writing elem > value (which requires operator> ), we simply translate the order into value < elem . This supports the only operator< requirement, but as a result, the order of the arguments is reversed.
This generalizes from elem < value to comp(elem, value) and value < elem to comp(value, elem) .
Ultimately, when designing, we can make two choices: we can use the same comparator everywhere, but for some algorithms the order of the arguments is reversed. Or we could use different comparators for each algorithm, depending on what makes sense for that particular algorithm. Using the same comparator around the world has many advantages - you just use the same comparator:
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<>{});
The same comparator is everywhere, the code looks right and does the right thing. If we flip the order of the arguments that upper_bound() goes to its comparator, we need to go to std::less<>{} . That would be just ... wrong.
You will probably be interested in Ranges TS , which solves this problem with invokable projectionions.
source share