How does begin() know which return type to return (const or non-const)?

In standard containers, a non-const iterator is implicitly convertible to a const_iterator. The type returned is based solely on the const-ness of the object/reference on which begin() was called, which in your case would be iterator, there is a conversion that allows the later assignment.

In particular in the 23.2.1 General Container Requirements, table 96, it says that X::iterator must be convertible to X::const_iterator.


list knows which kind of iterator to return because there are two begin methods defined, one for when the list is const, and one for when it isn't. The declarations might look something like this:

template<class T>
class list {
public:
    iterator<T> begin();
    const_iterator<T> begin() const;
}

In the following example, the first, non-const iterator would be returned, because the list isn't const:

void doSomething(list<int> &myList) {
    iterator<int> i = myList.begin();
    ...
}

In the next example, the list is declared as const, so the second version of begin that returns a const_iterator would be used instead:

void doSomethingElse(const list<int> &myList) {
    const_iterator<int> i = myList.begin();
    ....
}

Of course, an iterator can always be cast to a const_iterator, so you could declare i to be a const_iterator in either example, but if you try to declare i to be an iterator in the second example you'll get an error since a const_iterator can not be implicitly cast as an iterator.