Почему я не могу преобразовать обратный итератор в прямой итератор? - PullRequest
11 голосов
/ 10 декабря 2010

Ну, я знаю почему, потому что нет конверсии, но почему нет конверсии?Почему прямые итераторы могут быть обращены к обратным итераторам, а не наоборот?И что еще более важно, что я могу сделать, если я хочу сделать это?Есть ли какой-то адаптер, который позволяет выполнять итерацию в обратном направлении, используя прямой итератор?

Ответы [ 3 ]

17 голосов
/ 10 декабря 2010

Вы можете написать вспомогательную функцию. Одна особенность reverse_iterator заключается в том, что base() дает прямой итератор, следующий за значением, к которому обратный итератор обращается. Это потому, что обратный итератор физически указывает на элемент после того, который он логически указывает на . Таким образом, чтобы иметь прямой итератор для того же элемента, что и ваш reverse_iterator, вам нужно уменьшить результат base() на единицу, или , вы можете увеличить обратный итератор first , затем возьмите .base() этого.

Оба примера показаны ниже:

#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';
} 

Предупреждение: это поведение отличается от поведения конструктора reverse_iterator(iterator).

2 голосов
/ 08 декабря 2015

Очень часто два (обратных) итератора охватывают диапазон значений (например, в begin(),end() и rbegin(),rend()).Для любого диапазона, описанного двумя обратными итераторами rA,rB, диапазон rB.base(),rA.base() будет охватывать тот же диапазон в прямом направлении.

#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 << " ";
  }
}

Если концептуально вас интересует только один элемент (напримеррезультат find_if), затем используйте make_forward @visitor.Даже в этом случае идея диапазона помогает отслеживать действительность обратного итератора:

#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 голосов
/ 10 декабря 2010

Вы можете получить прямой итератор от обратного итератора, используя этот код

container.begin() + (reverseIter - container.rbegin() - 1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...