# STL's vector V.S. STL's set??

This is a discussion on STL's vector V.S. STL's set?? within the C++ Programming forums, part of the General Programming Boards category; Code: int tmp[]={3,2,1,3,2,4,5,4,2}; vector<int> vc(tmp,tmp+9); set<int> st(vc.begin(), vc.end()); vector<int>::iterator vit=vc.begin(); for(;vit<vc.end();it++) cout<<*it<<' '; // OK set<int>::iterator sit=st.begin(); for(;sit<st.end();it++) cout<<*it<<' '; ...

1. ## STL's vector V.S. STL's set??

Code:
```	int tmp[]={3,2,1,3,2,4,5,4,2};
vector<int> vc(tmp,tmp+9);
set<int> st(vc.begin(), vc.end());

vector<int>::iterator vit=vc.begin();
for(;vit<vc.end();it++) cout<<*it<<' '; // OK

set<int>::iterator sit=st.begin();
for(;sit<st.end();it++) cout<<*it<<' '; // Error
for(;sit!=st.end();it++) cout<<*it<<' '; // OK```
Why '<' is forbidden for SET's iterator?

2. Only random-access iterators can be compared using <, >, <=, or >= (this is to discourage their use for other types of iterators for which it would be horribly inefficient). For other types of iterators, you must use == and !=.

3. Many people will also tell you that you should be using != for a vector as well.
Also, you should use preincrement on your iterators (++it) not (it++).

4. Originally Posted by robatino
Only random-access iterators can be compared using <, >, <=, or >= (this is to discourage their use for other types of iterators for which it would be horribly inefficient). For other types of iterators, you must use == and !=.
It's a good idea to always use != even for iterators that support <. If you are doing generic programming (which you should strive for), you never know exactly what kind of iterator your code might be dealing with. So you should assume the lowest common denominator -- a forward iterator which supports == and != comparison, and not much else.

For the same reasons, it's better to increment an iterator with pre-increment instead of post-increment, because again, you never know exactly what functionality an iterator provides, and pre-increment is more fundamental than post-increment.

5. I used to think < in an integer loop required a subtraction and was less efficient than !=, and that this was why Stroustrup used != almost exclusively in his loops, until I realized that non-random access iterators weren't allowed to use <. Now I realize that < should be about as efficient as != for an integer loop (they both can be implemented by direct bit comparisons between integers), but I tend to use != anyway so I can write integer and iterator loops in the same way.

Edit:

> For the same reasons, it's better to increment an iterator with pre-increment instead of post-increment, because again, you never know
> exactly what functionality an iterator provides, and pre-increment is more fundamental than post-increment.

Looking at the table on page 551 of Stroustrup, I don't see any distinction made between pre- and post-increment with regard to being able to use them with iterators. I agree that it's a good habit to use pre-increment by default for efficiency reasons though.

6. Post-increment has to create a copy of the incremented object; pre-increment doesn't.

With todays processors, != and < should both be possible in one clock cycle.

7. in one clock cycle
It is too long for todays processors

1 instruction per tick count? You are definitely waisting your CPU power for nothing

8. Originally Posted by robatino
Looking at the table on page 551 of Stroustrup, I don't see any distinction made between pre- and post-increment with regard to being able to use them with iterators. I agree that it's a good habit to use pre-increment by default for efficiency reasons though.
That's for STL iterators. When dealing with user-written iterators, the user is often a lazy horse and doesn't write the post-increment operator. So the best generic classes/functions will always use pre-increment unless post-increment is absolutely necessary for some reason.

It's not really so much to do with efficiency -- modern inlining C++ compilers can usually completely optimize away the overhead of a post-increment, as long as the temporary value is not being used (e.g., in the increment phase of a for-loop).

9. Originally Posted by brewbuck
That's for STL iterators. When dealing with user-written iterators, the user is often a lazy horse and doesn't write the post-increment operator.
Then it's not a compliant iterator. The requirements on iterators say that post-increment must be present, even for the meanest input or output iterators, which you can't even copy and reuse. When concepts come in C++09, such half-iterators will be the first against the wall.

Besides, with the Boost.Iterator library, there's no excuse for doing this. Just defined increment(), and the library does the rest for you.

Or even if not using B.I, it's still an inexcusable laziness. Here, take this, copy and past, and correct the two type names.
Code:
```const type operator ++(int) {
type t(*this);
++*this;
return t;
}```

10. Originally Posted by CornedBee
Then it's not a compliant iterator. The requirements on iterators say that post-increment must be present, even for the meanest input or output iterators, which you can't even copy and reuse. When concepts come in C++09, such half-iterators will be the first against the wall.
Who cares? If you're writing your own generics why limit yourself to only non-broken classes? It's trivial to use pre-increment in an algorithm instead of post-increment and you gain the ability to work with non-compliant code while still working fine with compliant code.

Or even if not using B.I, it's still an inexcusable laziness.
Maybe, but not all the code I want to use is mine.

11. Originally Posted by brewbuck
Originally Posted by CornedBee
Or even if not using B.I, it's still an inexcusable laziness.
Maybe, but not all the code I want to use is mine.
If the code you're using was written by a developer lazy enough to not implement both operators, where else might the developer have been lazy?

12. Originally Posted by pianorain
If the code you're using was written by a developer lazy enough to not implement both operators, where else might the developer have been lazy?
By following this logic, any code with any flaw in it would have to be rejected.

Are you trying to say that any class which acts somewhat like an iterator but happens not to have a post-increment operator is somehow deficient? Why does it matter if such a class doesn't fit the precise definition of "iterator?" That's no reason not to be able to use it in a generic method.

My POINT which has been lost in standards trivia here, is that pre-increment is in many senses a more "generic" operation than post-increment, and should be preferred by default.

13. Are you trying to say that any class which acts somewhat like an iterator but happens not to have a post-increment operator is somehow deficient? Why does it matter if such a class doesn't fit the precise definition of "iterator?" That's no reason not to be able to use it in a generic method.
hmm... what if the class did not implement operator++ at all, and instead used a next() member function? After all, it acts somewhat like an iterator but happens not to have a pre-increment operator and post-increment operator. Why does it matter if such a class doesn't fit the precise definition of "iterator?" That's no reason not to be able to use it in a generic method.

My POINT which has been lost in standards trivia here, is that pre-increment is in many senses a more "generic" operation than post-increment, and should be preferred by default.
I think the generic operation is increment. The question is by what interface is this increment made possible.

14. Originally Posted by laserlight
hmm... what if the class did not implement operator++ at all, and instead used a next() member function? After all, it acts somewhat like an iterator but happens not to have a pre-increment operator and post-increment operator. Why does it matter if such a class doesn't fit the precise definition of "iterator?" That's no reason not to be able to use it in a generic method.
I understand your "whittling down" argument but it doesn't appear to have a base case At some point you have to accept that the classes you operate on conform to some specific interface, I just disagree with what that interface should be required to provide.

I see no harm in writing generic methods that can operate on STL-conformant objects AS WELL AS certain classes of NON-conformant objects. As the writer of a generic method shouldn't it be up to me what kinds of types my code can correctly operate on?

And anyway, is anybody seriously arguing AGAINST using pre-increment in favor of post-increment? My reasoning happens to be different than the usual efficiency argument, but the result is the same.

15. I'm arguing against avoiding post-increment where it makes the code more understandable, just because some broken code might not provide it.

By following this logic, any code with any flaw in it would have to be rejected.
No. Only the code where the flaw is a result of willful ignorance or laziness. If the flaw is an honest mistake, correct it and move on.