10

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?

iammilind
  • 68,093
  • 33
  • 169
  • 336
Thenewstockton
  • 443
  • 6
  • 18
  • 1
    [What do you mean?](http://coliru.stacked-crooked.com/a/4b5dfc7353b93dc6) – LogicStuff Jun 30 '16 at 10:58
  • Also related: [Why is it better to use '!=" than '<' in a vector loop? (C++)](http://stackoverflow.com/questions/871666/why-is-it-better-to-use-than-in-a-vector-loop-c) – iammilind Jun 30 '16 at 11:09
  • Mind you, you can only use `<` on two pointers _to the same array_, but not on unrelated pointers. – MSalters Jun 30 '16 at 12:28

3 Answers3

10

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.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 1
    Should be noted, though, that to be comparable, both iterators need to be in the same domain (iterating over same vector or whatever underlying class). – Aconcagua Jun 30 '16 at 11:05
  • I actually tried it with g++ along with -Wall -Wextra -std=c++11. It does not compile when you write it < myVector.end() – Thenewstockton Jun 30 '16 at 11:06
  • @user4099855 What's the error message? Did you check the comment of LogicStuff? – songyuanyao Jun 30 '16 at 11:07
  • Why the downvote? Where am I wrong? – songyuanyao Jun 30 '16 at 11:08
  • @songyuanyao Again one of those un-understandable ones - there seem to be some people randomly picking answers for downvoting... – Aconcagua Jun 30 '16 at 11:13
  • @user4099855 I tried with GCC and `-std=c++11` [here](http://coliru.stacked-crooked.com/a/e87815aadedfdcfa). It should be fine. – songyuanyao Jun 30 '16 at 11:21
  • @user4099855 worked for me, too, even with gcc 4.8.4 (`-std=c++1y`). – Aconcagua Jun 30 '16 at 11:28
  • Didn't the concept of `std::vector::iterator` actually change to ContiguousIterator? There's no page on cppreference yet so I can't easily check – KABoissonneault Jun 30 '16 at 13:22
  • @KABoissonneault The [accurate description](http://eel.is/c++draft/containers#container.requirements.general-13) is "A contiguous container is a container that supports random access iterators ([random.access.iterators]) and whose member types iterator and const_iterator are contiguous iterators ([iterator.requirements.general])." – songyuanyao Jun 30 '16 at 14:11
  • So, using `<` or `>` instead of `!=` **constraints** your generic algorithm to *random-access* iterators. – JFMR Mar 30 '19 at 12:27
4

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.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

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().

edmz
  • 8,220
  • 2
  • 26
  • 45
  • Any reason for downvoting? – edmz Jun 30 '16 at 11:15
  • Question was *'Why ...?'*, you're just giving an example, not the reason for (though downvote wasn't mine...). – Aconcagua Jun 30 '16 at 11:35
  • @Aconcagua Well, I think the reason is clear enough (_"only a few kinds of iterators support those operations"_) and the example shows a possible scenario for the issue. – edmz Jun 30 '16 at 11:59
  • I admit, the cited sentence actually *is* the answer to the question. It is somehow shadowed by your code example, though, a little bit as if you had a large flyer 'Hey see the drawback' and the explanation only in the fine print. You would have avoided the effect if the explanation was the first sencence of your answer... – Aconcagua Jun 30 '16 at 12:31
  • @Aconcagua Thanks for the tip! (I wasn't trying to accuse you, naturally) – edmz Jun 30 '16 at 13:07