2010-12-10 2 views
11

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

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 
+14

Существует преобразование: `backward.base();` – ybungalobill 2010-12-10 10:42:00

+0

Я уверен, что вы можете использовать `reverse_iterator `где необходимо, передавая тип итератора в качестве аргумента шаблона везде, где вы используете` iterator`. Разве это не решает вашу проблему? – Grozz 2010-12-10 10:45:30

+1

Вы абсолютно правы ybungalobill; мой фактический код немного сложнее этого, и я попробовал base(), но он дал мне ошибки, поэтому я сдался, и мой мозг стерли мои знания об этом. Благодаря! Если вы добавите этот точный текст в качестве ответа, я соглашусь с ним, так как действительно это * * ответ. – 2010-12-10 11:00:01

ответ

15

Вы можете написать вспомогательную функцию. Одна особенность reverse_iterator состоит в том, что base() дает передовой итератор, следующий за значением, которое имеет различие в обратном итераторе. This is because a reverse iterator physically points to the element after the one it logically points to. Итак, чтобы иметь передним итератором тот же элемент, что и ваш reverse_iterator, вам необходимо уменьшить результат base() на один, или, вы можете прирастить обратный итератор сначала, затем взять .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) конструктора.

0

Вы можете получить вперед итератор от обратного итератора с помощью этого кода

container.begin() + (reverseIter - container.rbegin() - 1); 
1

Это очень распространено иметь два (реверс) итераторы охватывают диапазон значений (например, в 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 
    } 
} 
Смежные вопросы