Rozważmy następującą sekwencję:Jak napisać opakowanie iteratora, które łączy w sobie grupy wartości sekwencyjnych z podstawowego iteratora?
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
mam wejściowych iteratory dla tej sekwencji. Chcę owinąć te iteratorów na iteratory które produkują następującą sekwencję zamiast:
(1,2), (3,4), (5,6), (7,8), (9,10)
Jeśli to nie jest jasne, to sekwencja to sekwencja kolejnych par kolejnych elementów z pierwotnego. Podczas gdy oryginał ma 10 elementów, ten ma 5: każdy jest otrzymywany z dwóch z oryginalnej sekwencji.
Używam doładowania na iterator_facade
zaimplementować to, i mam ten zły próbę to:
template <typename Iterator>
struct pairing_iterator
: boost::iterator_facade<
pairing_iterator<Iterator>,
std::array<typename std::iterator_traits<Iterator>::value_type, 2>,
std::input_iterator_category
// I should probably customize reference too, but it's not relevant
> {
pairing_iterator(Iterator it) : it(it) {
increment(); // A
}
pairing_iterator::value_type dereference() const {
return pair;
}
bool equal(pairing_iterator const& that) const {
return it == that.it; // B
}
void increment() {
pair = { { *it++, *it++ } };
}
Iterator it;
pairing_iterator::value_type pair;
};
Jeden problem mam skierowane jest na linii oznaczonej A: gdy iterator jest przekazywana w iterator końcowy, spowoduje to inkrementację, której nie mogę zrobić.
Kolejny znajduje się na linii oznaczonej literą B: Zachowuję pierwszy iterator zawsze przed "bieżącą" parą, więc jeśli iterator jest na ostatniej parze, to iterator będzie końcowym iteratorem, a tym samym porównać true z końcowym parametrem pairing_iterator.
Jeśli podstawowym iteratorem był forward iterator, mógłbym po prostu odczytać tę parę za każdym razem, gdy dokonano dereferencji, i po prostu dwa razy zwiększyć wartość kroku. Ale z Iteratory wejściowe mogę odczytać tylko raz.
Czy wymyślam nowe koło, które już istnieje? Nie znalazłem czegoś takiego w Boost, co mnie trochę zaskakuje. Ale chciałbym znaleźć gotowe rozwiązanie.
Jeśli to koło już nie ma, jak mogę je zmusić do rzucenia?
Moim zdaniem jest to podobne do iteratora filtrowania. Twierdzę, że najlepiej jest, aby iterator zawierał iterator końcowy, aby obsłużyć przypadek, w którym sekwencja niespodziewanie zawiera nieparzystą liczbę elementów. To również rozwiązałoby oba problemy (A i B), ponieważ wiesz, czy jest to iterator końca, i możesz oddzielić realizację pary proxy od inkrementacji podstawowego iteratora. (Nie jestem zaznajomiony z fasadą iteratora Boosta, więc nie jestem do końca pewien, jak można to przetłumaczyć na Boosteese). –
'Integer dereference()'? –
@ David Oops, to był artefakt ode mnie "zakupy zbędnych szczegółów z dala od przykładu :) –