Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

iterator

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 round? And more importantly, what can I do if I want to do this? Is there some adapter that allows you to iterate backwards using a forward iterator?

std::vector<int> buffer(10);
std::vector<int>::iterator forward = buffer.begin();
std::vector<int>::reverse_iterator backward = buffer.rbegin();
++forward;
++backward;
std::vector<int>::iterator forwardFromBackward = std::vector<int>::iterator(backward); // error! Can't convert from reverse_iterator to iterator!
std::vector<int>::reverse_iterator backwardFromForward = std::vector<int>::reverse_iterator(forward); // this is fine
like image 629
Ben Hymers Avatar asked Dec 10 '10 10:12

Ben Hymers


People also ask

How do you reverse a iterator in C++?

vector rbegin() and rend() function in C++ STL vector::rbegin() is a built-in function in C++ STL which returns a reverse iterator pointing to the last element in the container.

How do you use a forward iterator?

Forward iterators are used to read the contents from the beginning to the end of a container. Forward iterator use only increments operator (++) to move through all the elements of a container. Therefore, we can say that the forward iterator can only move forward. A Forward iterator is a multi-pass iterator.

What is a forward iteration?

A Forward Iterator is an iterator that corresponds to the usual intuitive notion of a linear sequence of values. It is possible to use Forward Iterators (unlike Input Iterators and Output Iterators) in multipass algorithms.


1 Answers

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.

like image 102
visitor Avatar answered Nov 15 '22 09:11

visitor