Как определить пользовательский итератор в переполнении стека

Я видел несколько постов на SO о том, как определять пользовательские итераторы, но ничего, что, кажется, точно не отвечает на мой вопрос, который …

Как мне создать итератор, который скрывает вложенный цикл for?

Например, у меня есть класс Foo, внутри Foo есть Bar, а внутри Bar — строка. Я мог бы написать

for (const Foo& foo : foo_set)
for (const Bar& bar : foo.bar_set)
if (bar.my_string != "baz")
cout << bar.my_string << endl;

но вместо этого я хочу иметь возможность сделать что-то вроде:

for (const string& good : foo_set)
cout << good << endl;

Как мне сделать что-то подобное?

2

Решение

Там были предложения и обсуждение сегментированные итераторы, но никто на самом деле не вошел в стандарт C ++ (пока, во всяком случае).

На данный момент, самый чистый способ справиться с этим (IMO, во всяком случае) — это набор предметов, каждый из которых сам является собранием:

std::ostream &operator<<(std::ostream &os, bar const &b) {
return os << b.my_string;
}

std::ostream &operator<<(std::ostream &os, foo const &f) {
std::remove_copy_if(f.begin(), f.end(),
std::ostream_iterator<bar>(os, "\n"),
[](bar const &b) { return b.my_string != "baz"; });

return os;
}

std::copy(foo_set.begin(), foo_set.end(),
std::ostream_iterator<foo>(std::cout, "\n"));

Или, если вы настаиваете:

for (auto s : foo_set)
std::cout << s << "\n";
2

Другие решения

Да.

Что, вы хотите больше деталей?

Это должно помочь многим:
http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/index.html#iterator-facade-and-adaptor

Или же:
http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/iterator_facade.html#usage
(функция ввода итератора также может хорошо работать).

Вы работаете на диапазонах. Внутреннее состояние итератора — это кортеж внутреннего итератора, внешнего итератора и флаг, указывающий, если вы находитесь в конце. Инкремент продвигает внутренний итератор, проверяет, равен ли он концу во внутреннем диапазоне, и, если это так, продвигает внешний итератор до тех пор, пока он не достигнет конца внешнего диапазона или непустого внутреннего диапазона (затем устанавливает внутренний итератор в начало внешний итератор, если внешний итератор не конечный!)

Разыменование просто разыменовывает внутренний итератор. Слепо! (хорошо, добавьте некоторые утверждения)

Равенство проверяет, чтобы внешний итератор был равен, и если да, то проверяет, установлен ли «конечный флаг». Если нет, он сравнивает внутренние итераторы равными. (Есть ли элегантный способ избежать этого флага конца?)

Получение первого элемента состоит из поиска итератора для первого непустого внутреннего диапазона.

Декремент немного сложно, но не обязательно для вашей задачи.

Необходимо соблюдать осторожность, чтобы избежать использования недопустимого внутреннего итератора, в то время как внешний итератор действителен. Я думаю, что перечислил большинство ошибок выше.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector