Изменение контейнера при использовании посетителя

Я реализовал шаблон посетителя на C++, используя итератор, подобный STL, для хранения текущей позиции посетителя в контейнере. Теперь я хотел бы изменить контейнер, пока я перебираю его, и меня особенно интересует удаление элементов из контейнера, даже того, который я сейчас посещаю.

Теперь, очевидно, это сделает недействительным внутренний итератор Посетителей, потому что он указывал именно на этот элемент. В настоящее время я храню список всех итераторов в контейнере и обновляю их, как только что-то добавляется в список или удаляется из него. Таким образом, это похоже на шаблон Observer, применяемый к итератору (как Observer) и списку (как Observable).

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

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

С уважением, Флориан

Обновление: над контейнером работает один посетитель, но внутри метода visit() может использоваться любое количество дополнительных итераторов для одного и того же контейнера. Я хочу, чтобы посетитель продолжал работать с оставшимися элементами в контейнере даже после того, как мы вернулись из вызова visit(), в котором какой-либо из элементов в контейнере был удален.


person Florian    schedule 15.04.2010    source источник
comment
Меня несколько смущает ваше описание. У вас есть несколько посетителей, работающих с контейнером, и все они должны обновляться, когда какой-либо посетитель вносит изменения? Вы хотите, чтобы посетитель повторно проверял свою позицию всякий раз, когда в контейнер вносятся какие-либо изменения, даже не посетителями? Или дело в том, что у вас есть только один посетитель за раз, и этот посетитель должен всегда покидать себя с действительным итератором после посещения элемента в контейнере?   -  person Matthew T. Staebler    schedule 15.04.2010
comment
Я тоже в замешательстве. Я думаю, что здесь могло бы помочь более подробное объяснение (или код) того, как вы реализовали посетителя через контейнер STL. Что принимает посетитель, объект и итератор? Кто меняет итераторы, чтобы посещался следующий элемент?   -  person David Rodríguez - dribeas    schedule 15.04.2010


Ответы (3)


При изменении контейнера во время обхода итераторы в лучшем случае опасны. Безопаснее всего использовать индекс и идти в обратном направлении.

person Marcelo Cantos    schedule 15.04.2010
comment
При использовании контейнера последовательности итераторы можно безопасно использовать даже при изменении контейнера. Вам просто нужно заменить итератор, который вы использовали, на итератор, возвращаемый методом вставки или стирания. - person Matthew T. Staebler; 15.04.2010
comment
Вы имеете в виду, например, «it = container.erase(it);»? Это звучит достаточно хорошо для меня, но как мне совместить это с шаблоном посетителя? - person Florian; 15.04.2010

Я думаю, что ваша (первая) реализация довольно хороша, если не так много итераторов и операций удаления. Если бы это было так, я бы использовал алгоритм метки и развертки, как рекомендовал Эдди. Кроме того, я думаю, что последнее проще и, следовательно, менее подвержено ошибкам. Не забудьте пропустить узлы, которые помечены для удаления. С другой стороны, если помимо «удаления» есть случаи, когда ваши итераторы необходимо обновить, придерживайтесь текущей реализации.

person ur.    schedule 15.04.2010

В этих случаях, если копирование моего контейнера не требует больших затрат, я просто копирую его и повторяю копию. Исходный контейнер содержит объекты по shared_ptr, в то время как копия содержит только weak_ptr.

person Peter G.    schedule 16.04.2010