Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++ why can't we compare iterators using > and <? [duplicate]

I have been asked this question which I do not really know why.

If you have a pointer int * x;
You can compare pointers with > and < because it stands for the memory location something like 0x0000 0x0004 0x0008, etc. I know iterators and pointers are different, but they act in a very similar way.

For example:

vector<int> myVector;

for(int i = 1; i < 101; i++)
{
    myVector.push_back(i);
}

vector<int>::iterator it = myVector.begin();
while(it != myVector.end()) //Why can't we write it < myVector.end()
{
    cout << *it << endl;
    it++;
}

Why can't we write it < myVector.end() in the while statement? I know it has to do with no overloading in STL. However, writing &*it < &*myVector.end() works because it gets the memory location which reveals say 0x0004 0x0008, etc.

Why is this?

like image 255
Thenewstockton Avatar asked Jun 30 '16 10:06

Thenewstockton


People also ask

Can we compare two iterators?

Equality and Inequality operator: Just like the input iterators, you can compare the equality of two output iterators.

Why use iterators instead of pointers?

After all, iterators are invalidated at mostly the same times and the same ways as pointers, and one reason that iterators exist is to provide a way to "point" at a contained object. So, if you have a choice, prefer to use iterators into containers.

How do you dereference an iterator?

3. Dereferencing: An input iterator can be dereferenced, using the operator * and -> as an rvalue to obtain the value stored at the position being pointed to by the iterator. 4. Incrementable: An input iterator can be incremented, so that it refers to the next element in the sequence, using operator ++().

Does std :: move invalidate iterators?

No, they should not get invalidated after a move operation.


3 Answers

The problem is that < and > cannot be always used with iterators, because only some kinds of iterators support such operations (namely, random access iterators and the like). On the other hand, comparison operations such as != is always available.

Now, why care about using < and > if != has the same effect and always works?


Suppose you have some generic code:

template <class It>
void foo(It begin, It end)
{
    while (--end != begin)
        apply(*begin);

}

The code will compile for pointers, for example, but it won't for myList.begin().

like image 143
edmz Avatar answered Oct 14 '22 18:10

edmz


operator< and operator> can only be used with RandomAccessIterator. But operator!= could also be used with InputIterator, ForwardIterator and BidirectionalIterator. For your sample code, it != myVector.end() and it < myVector.end() have the same effect, but the former is more general, then the code also works with other iterators (e.g. iterators of std::list or std::map etc).

BTW: Your sample code will be fine to use operator< or operator>, since the iterator of std::vector is RandomAccessIterator.

like image 24
songyuanyao Avatar answered Oct 14 '22 18:10

songyuanyao


std::vector::iterator is a random access iterator, and you can certainly compare them with < and >.

However, only random access iterators can be compared using anything other than == and !=. Bidirectional, forward, and input iterators only define the equality/inequality comparison operators.

A std::list::iterator, for example is an iterator pointing to some unspecified member of a std::list. In this case, there's just no meaning to any other kind of a comparison.

like image 33
Sam Varshavchik Avatar answered Oct 14 '22 18:10

Sam Varshavchik