C++98 containers defined two kinds of iterator, ::iterator
s and ::const_iterators
. Generally, like this:
struct vec{
iterator be
You can trivially convert any non-const iterator into a move iterator. It makes generally no difference to the container.
You cannot trivially convert non-const iterators to const iterators. For example, a copy-on-write string (std::string
in the past for some compilers, custom strings could still be this) has to pessimistically detach from shared data when a non-const iterator is taken (with begin()
) in order to fulfill typical invalidation guarantees, which is hugely inefficient when you just want a const iterator.
In addition, C++ overloading rules don't allow you to introduce an rvalue overload of begin()
without changing the unspecified version to lvalue, and that would be a breaking change.
Finally, overloading begin()
on rvalues is not useful anyway - the expectation is that rvalue functions are called on rvalues, and except for those produced by std::move
, these rvalues are 1) going away soon (which would invalidate the obtained iterator) and 2) have no name, which means that they can only be used in one expression, which means you cannot call both begin()
and end()
to obtain an iterator pair, and a single iterator is useless, since you can never know whether it's safe to dereference it.