I have always assumed that std::lower_bound() runs in logarithmic time if I pass a pair of red-black tree iterators (set::iterator or map::it
Great question. I honestly think there's no good/convincing/objective reason for this.
Almost all the reasons I see here (e.g. the predicate requirement) are non-issues to me. They might be inconvenient to solve, but they're perfectly solvable (e.g. just require a typedef to distinguish predicates).
The most convincing reason I see in the topmost answer is:
Although it is likely that there are parent pointers, requiring so for the tree seems inappropriate.
However, I think it's perfectly reasonable to assume parent pointers are implemented.
Why? Because the time complexity of set::insert(iterator, value) is guaranteed to be amortized constant time if the iterator points to the correct location.
Consider that:
How can you possibly avoid storing parent pointers here?
Without parent pointers, in order to ensure the tree is balanced after the insertion, the tree must be traversed starting from the root every single time, which is certainly not amortized constant time.
I obviously can't mathematically prove there exists no data structure that can provide this guarantee, so there's clearly the possibility that I'm wrong and this is possible.
However, in the absence of such data structures, what I'm saying is that this is a reasonable assumption, given by the fact that all the implementations of set and map I've seen are in fact red-black trees.
Side note, but note that we simply couldn't partially-specialize functions (like lower_bound) in C++03.
But that's not really a problem because we could have just specialized a type instead, and forwarded the call to a member function of that type.