Определить пользовательский (совместимый с STL) итератор, в котором тип значения не является CopyConstuctible или Assignable - PullRequest
0 голосов
/ 04 мая 2011

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

Основанием для этого является то, что итератор будет отвечать за перечисление модулей в Windows, и я использую API-интерфейсы CreateToolhelp32Snapshot / Module32First / Module32Next, чтобы избежать необходимости предварительной обработки всего списка модулей (например, каждое приращение итератора должно переходить к следующий модуль в списке по требованию, чтобы избежать ненужных накладных расходов.). Проблема заключается в том, что эти API требуют использования «РУЧКИ», управляемой API-интерфейсами Toolhelp, поэтому я не контролирую «позицию» в списке, кроме как при вызовах First / Next.

Я мог бы технически разрешить копирование дескриптора, но тогда вы столкнетесь с такими проблемами:

auto Iter1 = ModList.begin(); // Assume 'ModList' is an instance of my class which manages construction etc of my iterator
auto Iter2 = Iter1; // Both iterators now point to the first module in the list
++Iter1; // BOTH iterators now point to the second module in this list!! We just 'broke' the expected behavior of 'Iter2'.

Можно ли определить STL-совместимый итератор (который будет работать со стандартными алгоритмами и т. Д.), Который хорошо работает с типом значения, которое нельзя скопировать или присвоить?

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

Примечание: я мог бы сделать тип значения перемещаемым, если это поможет.

У меня уже есть сильная зависимость Boost в моей кодовой базе, поэтому не стесняйтесь предлагать решения, использующие Boost.

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

Ответы [ 2 ]

2 голосов
/ 04 мая 2011

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

Вы можете использовать его со стандартными алгоритмами, которые принимают InputIterator, то есть именно те, которые могут быть разумно реализованы как однопроходные, а не многопроходные алгоритмы.

В зависимости от того, проверяют ли реализации вашего алгоритма теги итератора, вы можете не получить никакой помощи, гарантируя, что вы не используете его неправильно. Нет никакой разницы в «сигнатуре» интерфейсов InputIterator и ForwardIterator, только в семантике, поэтому одна только утка во время компиляции не поможет.

1 голос
/ 04 мая 2011

Итератор должен логически ссылаться на элемент - он не должен быть элементом. Вам понадобится внутренняя коллекция модулей и итераторов, которые ссылаются на отдельные элементы в этой коллекции - как итераторы stdlib. Увеличение итератора должно заставить его изменить, к какому фактическому элементу он относится, без изменения бэкэнд-коллекции.

Для вашей конкретной проблемы вы могли бы создать коллекцию, которая продолжает итерацию всплывающей подсказки по требованию. Каждый раз, когда кто-то ссылается на модуль, к которому вы еще не обращались, вы заполняете дополнительные данные в коллекции.

...