I do not want to use std::distance
because it will calculate whole distance from my iterator to the end. But I need to be sure that I have N or more elements fr
The implementation of RB_Tree::iterator
increment operator in libstd++
makes sure it would not return an iterator to an undefined memory location:
static _Rb_tree_node_base*
local_Rb_tree_increment(_Rb_tree_node_base* __x) throw ()
{
if (__x->_M_right != 0)
{
__x = __x->_M_right;
while (__x->_M_left != 0)
__x = __x->_M_left;
}
else
{
_Rb_tree_node_base* __y = __x->_M_parent;
while (__x == __y->_M_right)
{
__x = __y;
__y = __y->_M_parent;
}
if (__x->_M_right != __y)
__x = __y;
}
return __x;
}
But the same is not true for std::vector
:
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> vec = {1,2};
auto it = vec.begin();
it = std::next(it, 5);
if (it != vec.end()) {
std::cout << "Not end..go on" << std::endl;
}
return 0;
}
This will go on printing the message..
So, since the behaviour is not same across containers, you should not depend on std::next
for its current correct behaviour for map
based containers.
next(it, n)
is undefined behavior if distance(it, c.end())
is less than n
.
[C++14: 5.7/5] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
See here for more info: Are non dereferenced iterators past the "one past-the-end" iterator of an array undefined behavior?
You must write a nextIfPossible
or your code is undefined. That said, since I'm guessing this is a Random Access Iterator, you'll find working with indexes to benchmark faster than working with iterators in the case where bounds checking must be performed: https://stackoverflow.com/a/37299761/2642059
So I'd recommend not even bothering with iterators or nextIfPossible
but just using an index and checking it against the size.
According to the standard §24.4.4/p3 & p6 Iterator operations [iterator.operations] (Emphasis Mine):
template <class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n);
2 Requires: n shall be negative only for bidirectional and random access iterators.
3 Effects: Increments (or decrements for negative n) iterator reference i by n.
template <class InputIterator> constexpr InputIterator next(InputIterator x, typename std::iterator_traits<InputIterator>::difference_type n = 1);
6 Effects: Equivalent to:
advance(x, n); return x;
Consequently, there's no bound checking and therefore you may result in undefined behaviour if input n
is greater than std::distance(it , c.end())
.