Why do you need a std function:advance, next, prev?
-
Standard library C+++ has functions
std::advance
♪std::next
♪std::prev
♪
Why do they need them and where should they be used?
-
Function
std::advance
previous functionsstd::next
andstd::prev
still in C++ 2003, while the last two functions appeared in the standardC++ 2011
♪Function
std::advance
has the following announcement:template <class InputIterator, class Distance> void advance(InputIterator& i, Distance n);
As can be seen from the announcement, the function changes the terator that has been referred to it as the first parameter.
However, practice has shown that it is very often necessary to create a new terator that is pre-emptive or later relative to the current iterator. In this case, I have had to resort to a pseudo code (I use the term pseudo code, because I use the key word in it.
auto
which, in C+ 2003, had not yet been the same as in C+ 2011 because, in the general case, iterators, with the exception of arbitrary access, did not have a combination of wholesale transactions:auto next = current; advance( next, n );
where
n
- a certain number.For example, we consider finding a maximum element in the second half of the elements of a list.
#include <list> #include <algorithm> #include <iterator>
// ...
std::list<int> lst;
// инициализация списка некоторыми значениями
std::list<int>::iterator it = lst.begin();
std::advance( it, lst.size() / 2 );it = std::max_element( it, lst.end() );
As a function
std::advance
Type of returnvoid
and she's changing her source as an argument, she's uncomfortable with algorithms. Additional announcements and code proposals are required to trigger an algorithm. Like, that's what the algorithm could look like.std::rotate
for the list using the functionstd::advance
#include <list>
#include <algorithm>
#include <iterator>// ...
std::list<int> lst;
// инициализация списка некоторыми значениями
std::list<int>::iterator middle = lst.begin();
std::advance( middle, lst.size() / 2 );
std::rotate( lst.begin(), middle, lst.end() );
In addition, the word
advance
Not quite successful when it comes to the calculation of the terators that precede the intended terator. In this case, it is necessary to indicate a negative value for the second argument of the function, which may be a source of error. For example,std::advance( middle, -1 );
It is difficult to conclude from this proposal whether
-1
It is indeed the intention of the programmer.Names like
prev
ornext
More clearly express the intentions of the programmer and make the code more readable.It was therefore suggested that the functions should be introduced.
std::prev
andstd::next
in standard C++ 2011. Moreover, these functions are being returned by the terator, and they can be built into algorithms. They do not alter the iterators, on the basis of which the functions are being returned by new heterans.Previous example of algorithm challenge
std::rotate
for the list now using these functions, one line may be added#include <list>
#include <algorithm>
#include <iterator>// ...
std::list<int> lst;
// инициализация списка некоторыми значениями
std::rotate( lst.begin(), std::next( lst.begin(), lst.size() / 2 ), lst.end() );
I mean, new iters or phrases with summer terators can be obtained without blocking the code for the announcements of intermediate variables that are required only to calculate algorithm arguments.
Iterators of arbitrary access can be folded with numerous expressions to obtain a new terator. For example,
std::vector<int> sequence = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::rotate( sequence.begin(), sequence.begin() + sequence.size() / 2, sequence.end() );
However, this code is not flexible. If for any reason you want to use another container that doesn't have arbitrary access, you're gonna have to change the algorithm proposal.
It would be much better if, even for the arbitrary access harbours, you would use the common functions.
std::vector<int> sequence = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::rotate( sequence.begin(), std::next( sequence.begin(), sequence.size() / 2 ), sequence.end() );
Especially these functions are irreplaceable when you write a template code for an arbitrary type of heteros.
Both functions
std::next
andstd::prev
have a default argument for the second parameter:template <class ForwardIterator>
ForwardIterator next(ForwardIterator x,
typename std::iterator_traits<ForwardIterator>::difference_type n = 1);template <class BidirectionalIterator>
BidirectionalIterator prev(BidirectionalIterator x,
typename std::iterator_traits<BidirectionalIterator>::difference_type n = 1);
These functions are therefore very convenient when the next or previous terator is required. For example,
std::vector<int> v = { /* некоторые значения */ };
auto after_first = std::next( v.begin() );
auto before_last = std::prev( v.end() );
It would be logical for a function
std::advance
also had a default argument for the second parameter. Then instead of expression, like,auto it = v.begin();
std::advance( it, 1 );
You could write it down easier.
auto it = v.begin();
std::advance( it );
And the word
advance
in this case would correspond to its direct meaning.I have made such a proposal to include a function in the declaration
std::advance
value of the argument for default1
for the second performance.With my proposal to change C++ with regard to the function
std::advance
click here http://cpp.forum24.ru/?1-3-0-00000076-000-0-0-1423215180