#c #windows #boost #stl #iterator
#c #Windows #повысить #stl #итератор
Вопрос:
Я хочу определить пользовательский итератор, который использует тип значения, который нельзя скопировать.
Обоснование этого заключается в том, что итератор будет отвечать за перечисление модулей в Windows, и я использую API CreateToolhelp32Snapshot / Module32First / Module32Next, чтобы избежать предварительной обработки всего списка модулей (например, приращение каждого итератора должно переходить к следующему модулю в списке по требованию, чтобы избежать ненужных накладных расходов.). Проблема с этим заключается в том, что эти API требуют использования «HANDLE» управляется 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 Дайте мне знать, если требуется разъяснение.
Комментарии:
1. Мне кажется, что вам действительно нужен функтор генератора, а не итератор.
Ответ №1:
Если вы пометите свой итератор как InputIterator, а не ForwardIterator, то описанное вами поведение не будет неожиданным. Увеличение InputIterator делает недействительными его копии, поэтому не имеет значения, на что они указывают после этого.
Вы можете использовать его со стандартными алгоритмами, которые принимают InputIterator, то есть именно те, которые могут быть разумно реализованы как однопроходные, а не многопроходные алгоритмы.
Однако, в зависимости от того, проверяют ли реализации вашего алгоритма теги итератора, вы можете не получить никакой помощи, гарантирующей, что вы не используете его неправильно. Нет разницы в «подписи» интерфейсов InputIterator и ForwardIterator, только в семантике, поэтому один только ввод во время компиляции не помогает.
Комментарии:
1. Ах, тогда, я думаю, это должно быть идеально. Я чувствую себя таким глупым сейчас.
2. Итак, если увеличение копии такого итератора делает недействительными другие, тогда зачем вообще разрешать копии?
3. @SasQ: потому что в противном случае (в C 03, когда были указаны требования к итератору) было бы невозможно передавать и возвращать итераторы по значению. Если бы итераторы были новыми в C 11, тогда, возможно, имело бы смысл требовать, чтобы InputIterators были подвижными, а не копируемыми, и сделать copyable требованием ForwardIterator .
Ответ №2:
Итератор должен логически ссылаться на элемент — он не должен быть элементом. Вам понадобится внутренняя коллекция модулей и итераторы, которые ссылаются на отдельные элементы в этой коллекции — точно так же, как итераторы stdlib. Увеличение итератора должно заставить его изменить, к какому фактическому элементу он относится, без изменения внутренней коллекции.
Для вашей конкретной проблемы вы могли бы создать коллекцию, которая продолжает итерацию toolhelp по требованию, всякий раз, когда кто-то ссылается на модуль, к которому вы еще не выполняли итерацию, вы добавляете дополнительные данные в коллекцию.
Комментарии:
1. Я понимаю это, однако я пытаюсь сделать это, чтобы избежать ненужного снижения производительности в противном случае. Если пользователь найдет то, что он хочет, скажем, после двух модулей, я хочу, чтобы они заплатили только за эти два модуля. Не для предварительной обработки всего списка.
2. @RaptorFactor: по требованию или создайте итератор ввода (если это подходит для вашего использования)
3. На самом деле, я думаю, если бы я заставил серверную часть просматривать список по требованию, затем кэшировать результаты и сохранить состояние итераторов, в котором указано, на какой элемент в списке, на который они ссылаются, это могло бы сработать… Хотя я не уверен, мне нужно было бы подумать об этом еще немного. Звучит ли это более разумно?
4. Итератор ввода в порядке, но разве у меня все еще нет проблемы, которую я описал в примере кода?
5. @RaptorFactor: ни один стандартный алгоритм, который принимает InputIterator, не будет выполнять то, что вы описываете (возьмите копию итератора и ожидайте, что он все еще будет ссылаться на referand после увеличения оригинала). Таким образом, проблем нет. Алгоритмы, которые выполняют то, что вы описываете, будут помечены как требующие, по крайней мере, ForwardIterator . Интерфейс InputIterator предназначен для выполнения итераций, например, по небуферизованным, недоступным для просмотра потокам. Как и в вашем случае, такой тип итератора не может «запоминать» прошлые позиции.