While iterating through a std::map or std::vector or any container which has iterator in it, is checked against the variable.end() and not something like container<>::end. For example,
map<int, int> var;
for(map<int, int>::iterator it = var.begin(); it != var.end(); it++)
... ^^^^^^^^^^^^^^^
Can’t above highlighted part be something like:
it != map<int,int>::end
which is similar to static member string::npos. What can be the reason behind the design decision for providing .end() on per variable bases and not on the per type of container bases ? (i.e. map<int,int>::end and map<int,double>::end would be different; but for every map<int,int> variable, the ::end will be similar.)
Iterators are for iterating, moving forward and backward. They need to provide increment and decrement (bidirectional iterators) operations. When you decrement an end() iterator, you get to the last item in the container. This allows iterating backwards.
As to your suggestion. Implementing this would mean that each iterator carries the end iterator with it, and compares equal to the static end iterator when it is equal to the real end iterator it is storing. There would actually be no point to make all the static end iterators different types, because that “iterator” cannot be used for anything other than that anyway.
A design like that would simply be more cumbersome to implement and more wasteful to use. If each iterator has to know the end of its container, then to designate an arbitrary range, you’d have to add two potentially unused iterators to the end in the mix.