Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if two iterators come from same object

Given two std::iterators of the same type, how is it possible to test if the come from the same object (not class)? Note, I'm not asking how to compare their values.

std::string foo = "foo";
std::string bar = "bar";

std::string::iterator iter1 = foo.begin();
std::string::iterator iter2 = bar.begin();

if ( iter1 == iter2 )
{
    ...
}

The above should and does fail. How can I check for this at runtime? Looking into the source code, I see that the relevant methods call on iterator::_Compat() this is a void method that does the check I want but on failure it issues a debug assertation. It will go unnoticed in release builds.

Looking further I see that the iterator (for string at least) has a public _GetCont() method. So

if ( iter1._GetCont() == iter2._GetCont() )

works. But, this is undocumented leading me to believe it's not safe to use.

My question is how can I accomplish the above in a portable manner?

Also to note, this is part of an iterator template class. I will have no control over the second iterator.

like image 401
Twifty Avatar asked Jul 05 '13 15:07

Twifty


People also ask

How do you compare two iterators?

To compare the values that two iterators are pointing at, dereference the iterators first, and then use a comparison operator. Operator= -- Assign the iterator to a new position (typically the start or end of the container's elements).

Can you compare iterators C++?

The output iterator in C++ has the following salient features: Equality and Inequality operator: Just like the input iterators, you can compare the equality of two output iterators.


1 Answers

My question is how can I accomplish the above in a portable manner?

You cannot.

In general, iterators are not required to know (or let you know) about the container they point into. Iterators are a generalization of pointers, and all they are required to do is to behave like pointers.

So they may allow dereferencing, incrementing, decrementing, summing, and so on, depending on their category, but there is no iterator requirement in the C++ Standard about letting their user know what container they point into, or whether they point into the same container as another iterator.

In other words, the validity of an iterator range should be a precondition of a function that works on that iterator range. It is a responsibility of the client to ensure the provided iterators point into the same container (and that the second iterator is reachable from the first).

For instance, here is how the Standard Library deals with this matter (paragraph 24.2.1/7 of the C++11 Standard):

Most of the library’s algorithmic templates that operate on data structures have interfaces that use ranges. A range is a pair of iterators that designate the beginning and end of the computation. A range [i,i) is an empty range; in general, a range [i,j) refers to the elements in the data structure starting with the element pointed to by i and up to but not including the element pointed to by j. Range [i,j) is valid if and only if j is reachable from i. The result of the application of functions in the library to invalid ranges is undefined.

like image 146
Andy Prowl Avatar answered Oct 06 '22 13:10

Andy Prowl