Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

ISO C++11 24.3:

template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n);
// ...
template <class ForwardIterator>
ForwardIterator next
(
    ForwardIterator x,
    typename std::iterator_traits<ForwardIterator>::difference_type n = 1
);

Why std::next does not accept InputIterators?

One of legal use cases I am thinking about is:

first = find(next(first, x), last, 11); // ...

I have found appropriate DR:

next/prev return an incremented iterator without changing the value of the original iterator. However, even this may invalidate an InputIterator. A ForwardIterator is required to guarantee the 'multipass' property.

But I don't understand how multipass/invalidation is related to that. Using same multipass/invalidation reasoning, we can even ban std::find for InputIterators:

template<class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& value);

There is nothing special about std::next in compare to std::find or std::vector::insert(pos, first, last) which have perfectly legal use cases for InputIterators

Moreover std::next(it, n) can be used in generic code, which operates not only on InputIterators.

share|improve this question
2  
Except there's std::advance to more accurately convey your semantics for InputIterators. We've been over this in chat –  sehe Oct 27 '13 at 0:15
2  
Such code can be used in generic functions which work on all iterators starting from InputIterator. I am interested to hear objective reasons. –  Evgeny Panasyuk Oct 27 '13 at 0:16
    
On a different note. Shouldn't all this be overhauled, in light of features from C++11. Perhaps something like an InputIterator should be movable, not copyable, to emphasize that we can't really have to different iterators to the same source? (But then it should all be sorted out with ranges and so on. A big overhaul, perhaps.) –  Aaron McDaid Oct 27 '13 at 0:31
1  
@EvgenyPanasyuk: It isn't. Read the first paragraph of rici's answer to find out more about input iterators and how they work. –  Lightness Races in Orbit Oct 27 '13 at 1:27
1  
@EvgenyPanasyuk: You're free, of course, to continue repeating that assertion on every answer and as a reply to every comment... –  Lightness Races in Orbit Oct 27 '13 at 1:53
show 6 more comments

1 Answer

up vote 7 down vote accepted

In effect, input iterators cannot be usefully copied, because once an input iterator is incremented, any copy left lying around is invalidated.

std::next takes an iterator and returns another iterator which has been advanced n times. You can't do that with an input iterator without invalidating the original iterator, which makes std::next pointless. By constrast, std::advance advances the specified iterator n times, which is fine with an input iterator.

std::next is the iterator generalization of operator+(T*, size_t). std::advance is the iterator generalization of operator+=(T*&, size_t). It may well be that std::advance, like operator+=, should return a reference instead of void.

It's true that there is a similar issue with std::find (and related functions); they, too, will invalidate any copy of the specified input iterators. But it is quite possible that the committee found that issue less serious.

share|improve this answer
    
first = find(next(first, x), last, 11); is not pointless, it is legal use-case. I don't see why you think find is OK, but next is not - there is same invalidation. –  Evgeny Panasyuk Oct 27 '13 at 0:25
2  
@evgeny: you're free to use advance(first, x); first = find(first, last, 11);. Perhaps "pointless" is not quite the right word; I mean it is pointless to pretend that it's possible to return a different iterator. –  rici Oct 27 '13 at 0:28
    
I know that it is possible to use advance. It is even possible to use advance instead of next for higher iterators categories. std::next was introduced for convenience in a first place. "You can't do that with an input iterator without invalidating the original iterator" - same is applied to std::find. –  Evgeny Panasyuk Oct 27 '13 at 0:40
1  
@EvgenyPanasyuk: I think you misphrased your question. You asked "why does the standard say ...?". You meant to ask "Don't you agree that the standard is wrong?". Of course, had you phrased your question that way, it probably would have been immediately closed as "primarily opinion-based". –  rici Oct 27 '13 at 0:45
1  
No, my objection is about interface of std::next. Even if it uses advance internally, or closely related to it - interface of std::next should be fixed by itself. There is nothing special about std::next in compare to std::find or std::vector::insert(pos, first, last) which have perfectly legal use cases for InputIterators. –  Evgeny Panasyuk Oct 27 '13 at 1:13
show 6 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.