Why can I not convert a reverse iterator to a forward iterator?

前端 未结 3 1504
情话喂你
情话喂你 2021-02-13 22:36

Well, I know why, it\'s because there isn\'t a conversion, but why isn\'t there a conversion? Why can forward iterators be turned to reverse iterators but not the other way roun

相关标签:
3条回答
  • 2021-02-13 22:48

    You can get forward iterator from reverse iterator using this code

    container.begin() + (reverseIter - container.rbegin() - 1);
    
    0 讨论(0)
  • 2021-02-13 22:56

    You could write a helper function. One particularity of reverse_iterator is that base() gives a forward iterator that is next from the value that the reverse iterator dereferences to. This is because a reverse iterator physically points to the element after the one it logically points to. So to have the forward iterator to the same item as your reverse_iterator, you'll need to decrement the result of base() by one, or you could increment the reverse iterator first, then take the .base() of that.

    Both examples are shown below:

    #include <iostream>
    #include <vector>
    #include <iterator>
    
    //result is undefined if passed container.rend()
    template <class ReverseIterator>
    typename ReverseIterator::iterator_type make_forward(ReverseIterator rit)
    {
        return --(rit.base()); // move result of .base() back by one.
        // alternatively
        // return (++rit).base() ;
        // or
        // return (rit+1).base().
    }
    
    int main()
    {
        std::vector<int> vec(1, 1);
        std::vector<int>::reverse_iterator rit = vec.rbegin();
        std::vector<int>::iterator fit = make_forward(rit);
        std::cout << *fit << ' ' << *rit << '\n';
    } 
    

    Warning: this behavior is different from that of the reverse_iterator(iterator) constructor.

    0 讨论(0)
  • 2021-02-13 23:04

    It's very common to have two (reverse) iterators span a range of values (such as in begin(),end() and rbegin(),rend()). For any range described by the two reverse iterators rA,rB, the range rB.base(),rA.base() will span the same range in the forward direction.

    #include <iostream>
    #include <iterator>
    #include <vector>
    
    int main() {
      std::vector<int> vec{10,11,12,13,14,15};
    
      // spans the range from 13 to 10
      auto rfirst=std::rbegin(vec)+2;
      auto rlast=std::rend(vec);
    
      // Loops forward, prints 10 11 12 13
      for(auto it = rlast.base(); it != rfirst.base(); ++it){
        std::cout << *it << " ";
      }
    }
    

    If conceptually you are only interested in a single item (such as the result of find_if), then use make_forward by @visitor. Even in this case, the range idea helps to keep track of the validity of the reverse iterator:

    #include <iostream>
    #include <iterator>
    #include <vector>
    #include <algorithm>
    
    int main() {
      std::vector<int> vec{10,11,12,13,14,15};
    
      auto rfirst=std::rbegin(vec);
      auto rlast=std::rend(vec);
    
      auto rfound = std::find_if(rfirst,rlast, [](int v){ return v<13; });
    
      if(rfound != rlast){
        std::cout << *rfound << " "; // prints 12
        auto forwardFound = make_forward(rfound) ; 
        std::cout << *forwardFound << " "; // prints 12
      }
    }
    
    0 讨论(0)
提交回复
热议问题