There are good "design philosophy" reasons for not providing those overloads. In particular, the whole STL containers / algorithms interaction is designed to go through the different iterator concepts such that those two parts remain independent, so that you can define new container types without having to overload for all the algorithms, and so that you can define new algorithms without having to overload for all the containers.
Beyond those design choices, there is a very good technical reason why these algorithms (sort, lower-bound, etc..) cannot be overloaded for the special containers like list
or map
/ set
. The reason is that there is generally no reason for iterators to be explicitly connected to their parent container. In other words, you can get list iterators (begin / end) from the list container, but you cannot obtain (a reference to) the list container from a list iterator. The same goes for map / set iterators. Iterators can be implemented to be "blind" to their parent container. For example, a container like list
would normally contain, as data members, pointers to the head and tail nodes, and the allocator object, but the iterators themselves (usually just pointers to a node) don't need to know about the head / tail or allocator, they just have to walk the previous / next link pointers to move back / forth in the list. So, if you were to implement an overload of std::sort
for the list
container, there would be no way to retrieve the list container from the iterators that are passed to the sort function. And, in all the cases you mentioned, the versions of the algorithms that are appropriate for those special containers are "centralized" in the sense that they need to be run at the container level, not at the "blind" iterator level. That's why they make sense as member functions, and that's why you cannot get to them from the iterators.
However, if you need to have a generic way to call these algorithms regardless of the container that you have, then you can provide overloaded function templates at the container level if you want to. It's as easy as this:
template <typename Container>
void sort_container(Container& c) {
std::sort(begin(c), end(c));
};
template <typename T, typename Alloc>
void sort_container(std::list<T, Alloc>& c) {
c.sort();
};
template <typename Key, typename T, typename Compare, typename Alloc>
void sort_container(std::map<Key, T, Compare, Alloc>&) { /* nothing */ };
//... so on..
The point here is that if you are already tied in with STL containers, then you can tie in with STL algorithms in this way if you want to... but don't expect the C++ standard library to force you to have this kind of inter-dependence between containers and algorithms, because not everyone wants them (e.g., a lot of people really like STL algorithms, but have no love for the STL containers (which have numerous problems)).