TL DR: Due to historical reasons.
I think it is more or less obvious why ForwardIterator and other more functional iterators should be copyable. As for InputIterator and OutputIterator , the situation is a bit more complicated.
InputIterator and OutputIterator have a one-pass nature, which goes well with the concept of a motion-only class. Now, when you use any of these iterators from the standard library (say, istream_iterator for example), you can copy it and dereference the copy, but promoting any of the copies will advance all of them, which does not look like the expected behavior.
Unfortunately, at the time of writing many STL algorithms (for example, std::find_if , std::copy , etc.) there was no movement semantics at all, and there was no way to require that InputIterator constructive.
Since then, on some platforms, STL algorithms actually require the iterator to be specified as copyable (as in this case), as well as on other platforms (for example, g ++ AFAIK), this behavior is required by the concept of InputIterator , which is checked at compile time every time when you use STL algorithms.
In addition, you may find this answer helpful.
source share