std::next with n > std::distance(it, c.end())

后端 未结 3 1873
清歌不尽
清歌不尽 2020-12-19 23:53

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

相关标签:
3条回答
  • 2020-12-20 00:06

    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.

    0 讨论(0)
  • 2020-12-20 00:16

    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.

    0 讨论(0)
  • 2020-12-20 00:22

    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()).

    0 讨论(0)
提交回复
热议问题