Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does not std::advance return the resulting iterator?

Currently, std::advance is designed like this:

template< class InputIt, class Distance >
void advance( InputIt& it, Distance n );

However, I frequently find myself want something like:

template< class InputIt, class Distance >
InputIt advance( InputIt it, Distance n );

So, what is the rationale behind the current design? Is this for some performance consideration? Note that std::next and std::prev do return the resulting iterator.

like image 747
Lingxi Avatar asked Jun 21 '15 15:06

Lingxi


People also ask

How do you advance an iterator in C++?

std::advance in C++. std::advance advances the iterator ‘it’ by n element positions. Syntax : template void advance (InputIterator& it, Distance n); it : Iterator to be advanced n : Number of element positions to advance. This shall only be negative for random-access and bidirectional iterators.

What is the behavior of negative n in input iterator?

If n is negative, the iterator is decremented. In this case, InputIt must meet the requirements of LegacyBidirectionalIterator, otherwise the behavior is undefined. - InputIt must meet the requirements of LegacyInputIterator . Linear. However, if InputIt additionally meets the requirements of LegacyRandomAccessIterator, complexity is constant.

When is the behavior of an iterator defined to be undefined?

The behavior is undefined if the specified sequence of increments or decrements would require that a non-incrementable iterator (such as the past-the-end iterator) is incremented, or that a non-decrementable iterator (such as the front iterator or the singular iterator) is decremented. See also the implementations in libstdc++ and libc++ .


1 Answers

There is no technical reason preventing it to return a reference to the input value, and any reasonable compiler should be able to optimize the return value out if it's not used. So they could have done it that way if they wanted to.

I think their choice makes sense from an API design point of view though - std::prev and std::next take an iterator and return a different iterator pointing to the previous or next element, respectively, without modifying the input.

std::advance on the other hand modifies the input. If it returned a reference to the input iterator, it might be confused for a function that returns a copy without modifying the input in-place. That could potentially be dangerous.

Note that std::advance works with InputIterators, which includes iterators where iteration has side effects (things such as iterators that read from streams), but std::prev and std::next only work with ForwardIterators, which do not have side effects.

So returning a separate value (like std::prev and std::next) would be a bad idea - you'd end up with two iterators on the same stream, which may affect each other adversely.

like image 61
AaronI Avatar answered Oct 28 '22 20:10

AaronI