简体   繁体   中英

Define Custom (STL-compatible) Iterator where Value Type is not CopyConstuctible or Assignable

I wish to define a custom iterator which uses a value type that can not be copied.

The rationale for this is that the iterator will be responsible for module enumeration under Windows, and I'm using the CreateToolhelp32Snapshot/Module32First/Module32Next APIs to avoid having to preprocess the entire module list (eg Each iterator increment should advance to the next module in the list on demand to avoid unnecessary overhead.). The problem with this is that these APIs require the use of a 'HANDLE' managed by the Toolhelp APIs, so I have no control over the 'position' in the list other than by calls to First/Next.

I could technically allow copying of the handle, but then you run into problems like this:

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'.

Is it possible to define an STL-compatible iterator (that will work with the standard algorithms etc) that plays nice with a value type that cannot be copied or assigned?

I could also wrap the value type in a shared pointer in the implementation of the iterator, and that would make the iterator itself copyable and assignable, but it still doesn't solve the problem outlined in the code above.

Note: I could make the value type moveable if that helps.

I already have a heavy Boost dependency in my code base so feel free to suggest solutions which use Boost.

Sorry for the poorly written question, I've been up for quite a while and my brain doesn't want to work properly anymore. :P Let me know if clarification is needed.

If you tag your iterator as an InputIterator rather than a ForwardIterator, then the behavior you describe is not unexpected. Incrementing an InputIterator invalidates copies of it, so it doesn't matter what they appear to point to after that.

You can use it with standard algorithms that accept an InputIterator, which is exactly those that can reasonably be implemented as single-pass rather than multi-pass algorithms.

Depending whether your algorithm implementations check iterator tags, though, you may not get any help ensuring that you don't use it incorrectly. There's no difference in the "signature" of the InputIterator and ForwardIterator interfaces, only in the semantics, so compile-time duck typing alone doesn't help.

An iterator should logically refer to an element - it shouldn't be an element. You'll need a backend collection of modules, and iterators that refer to individual elements in this collection - just like the stdlib iterators. Incrementing an iterator should make it change which actual element it refers to, without modifying the backend collection.

For your particular problem, you could make a collection which continues the toolhelp iteration on demand, whenever someone refers to a module you haven't yet iterated to, you fill in more data in the collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM