comparing iterators from different containers
Is it legal to compare iterators from different containers?
std::vector<int> foo;
std::vector<int> bar;
Does the expression foo.begin() == bar.begin()
yield false or undefined behavior?
(I am writing a custom iterator and stumbled upon this question while implementing operator==
.)
If you consider the C++11 standard (n3337):
§ 24.2.1 — [iterator.requirements.general#6]
An iterator
j
is called reachable from an iteratori
if and only if there is a finite sequence of applications of the expression++i
that makesi == j
. Ifj
is reachable fromi
, they refer to elements of the same sequence.
§ 24.2.5 — [forward.iterators#2]
The domain of
==
for forward iterators is that of iterators over the same underlying sequence.
Given that RandomAccessIterator
must satisfy all requirements imposed by ForwardIterator
, comparing iterators from different containers is undefined.
The LWG issue #446 talks specifically about this question, and the proposal was to add the following text to the standard (thanks to @Lightness Races in Orbit for bringing it to attention):
The result of directly or indirectly evaluating any comparison function or the binary - operator with two iterator values as arguments that were obtained from two different ranges r1 and r2 (including their past-the-end values) which are not subranges of one common range is undefined, unless explicitly described otherwise.
Undefined behavior as far as I know. In VS 2010 with
/*
* to disable iterator checking that complains that the iterators are incompatible (come from * different containers :-)
*/
#define _HAS_ITERATOR_DEBUGGING 0
std::vector<int> vec1, vec2;
std::vector<int>::iterator it1 = vec1.begin();
std::vector<int>::iterator it2 = vec2.begin();
if (it1 == it2)
{
std::cout << "they are equal!!!";
}
The equality test returns in this case true :-), since the containers are empty and the _Ptr member of the iterators are both nullptr.
Who knows maybe your implementation does things differently and the test would return false :-).
EDIT:
See C++ Standard library Active Issues list "446. Iterator equality between different containers". Maybe someone can check the standard to see if the change was adopted?
Probably not since it is on the active issues list so Charles Bailey who also answered this is right it's unspecified behavior.
So I guess the behavior could differ (at least theoretically) between different implementations and this is only one problem.
The fact that with iterator debugging enabled in the STL implementation that comes with VS checks are in place for this exact case (iterators coming from different containers) singnals at least to me once more that doing such comparisons should be avoided whenever possible.
You cannot directly compare iterators from different containers. An iterator is an object that uses the internal state of a container to traverse it; comparing the internals of one container to another simply does not make sense.
However, if the iterators resulting from container.begin()
are available, it may make sense to compare iterators by the count of objects traversed from begin()
to the current iterator value. This is done using std::distance
:
int a = std::distance(containerA.begin(), iteratorA);
int b = std::distance(containerB.begin(), iteratorB);
if (a <comparison> b)
{ /* ... */ }
Without more context, it's difficult to judge whether this would solve your problem or not. YMMV.