It would be easier to understand/remember what std::lower_bound() and std::upper_bound() return knowing that std::equal_range() returns a pair of iterators, where the first one is equal to what std::lower_bound() returns, and the second one is equal to what std::upper_bound() returns.
So, here are different cases when they are called with a parameter of 4:
1 2 3 4 4 4 4 5 E
| |
F S - first points to the first element, second to the one behind last, representing range which contains 4
1 2 3 4 5 E
| |
F S same for one element
1 2 3 4 E
| |
F S same as before, but 4 is the last element
1 2 3 5 E
|
F==S first == second, which means range for elements equal to 4 is empty
1 2 3 E
|
F==S same as before but there is no element greater than 4
Where E means what container.end() returns - an iterator behind the last element.