Consider the following code:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec{1,2,3,5};
for(auto it=vec.cbegin();it!=vec.cend();++it)
{
std::cout << *it;
// A typo: end instead of cend
if(next(it)!=vec.end()) std::cout << ",";
}
std::cout << "\n";
}
Here I've introduced a typo: in the comparison I called vec.end()
instead of vec.cend()
. This appears to work as intended with gcc 5.2. But is it actually well-defined according to the Standard? Can iterator
and const_iterator
be safely compared?
Surprisingly, C++98 and C++11 didn't say that you can compare a
iterator
with aconst_iterator
. This leads to LWG issue 179 and LWG issue 2263. Now in C++14, this is explicitly permitted by § 23.2.1[container.requirements.general]p7Table 96 in the C++11 Standard, in section 23.2.1, defines the operational semantics of
a.cend()
for any container typeX
(includingstd::vector
) as follows:So the answer is yes because by this definition
cend()
refers to the same element/position in the container asend()
, andX::iterator
must be convertible toX::const_iterator
(a requirement also specified in the same table(*)).(The answer is also yes for
begin()
vs.cbegin()
for the same reasons, as defined in the same table.)(*) It has been pointed out in comments to other answers that convertibility does not necessarily imply that the comparison operation
i1==i2
will always work, e.g. ifoperator==()
is a member function of the iterator type, the implicit conversion will only be accepted for the righthand-side argument, not the lefthand-side one. 24.2.5/6 states (about forward-iteratorsa
andb
):Even though the iterators
end()
andcend()
are not dereferenceable, the statement above implies thatoperator==()
must be defined in such a way that the comparison is possible even ifa
is a const-iterator andb
is not, and vice versa, because 24.2.5 is about forward-iterators in general, including both const- and non-const-versions -- this is clear e.g. from 24.2.5/1. This is why I am convinced that the wording from Table 96, which refers to convertibility, also implies comparability. But as described in cpplearner@'s later answer, this has been made explicitly clear only in C++14.See §23.2.1, Table 96:
[...]
So, yes, it is well-defined.