What does lower_bound mean. If I had to guess I would answer that this function returns the iterator at the last element that is less than the value asked for. But I see tha
Following David Hammen's answer, I attempted to explain why we often don't feel the names of lower_bound/upper_bound to be correct, or at least intuitive.
It's because we are looking for an element immediately lower than the query. I made a drawing and a use case:
Code:
template< typename T, typename U >
auto infimum(std::map const& ctr, T query)
{
auto it = ctr.upper_bound(query);
return it == ctr.begin() ? ctr.cend() : --it;
}
template< typename T, typename U >
bool is_in_interval(std::map const& ctr, T query)
{
auto inf = infimum(ctr, query);
return inf == ctr.end() ? false : query <= inf->second;
}
https://ideone.com/jM8pt3
Basically to get the behavior of the "grey arrows", we need upper_bound - 1 which is why it's weird.
Let me rephrase that slightly: from the name lower_bound we instinctively expect returns-first-immediately-inferior-element (like the grey arrows). But we get returns-first-immediately-superior-element for lower_bound; and first-immediately-strictly-superior-element for upper_bound. That's what is surprising.
It's surprising in the hypothesis that you work with a sparse sequence like my thought experiment in the picture above. But it makes wonderful sense when you think of it in terms of «bounds of an equal_range» in a dense sequence, populated with plateaus, like Kerrek SB beautifully pictured.
Test code:
#include
results in
red->first 2
green->first 2
pink->first 8
red is in 1
green is in 0
pink is in 1
yellow is in 0
seems ok.
So of course the utility functions are not very good, they should be designed with a range API, so we can work with any collection or sub-range, or reverse iterators, or filtered views and whatnot. We can get that when we have C++20. In the meantime, I just made a simple educative map-taking API.
play with it:
https://ideone.com/jM8pt3