Reputation:
According to en.cppreference.com and VC++ 14.0, iterators need to have copy constructors and copy assignment operators.
My iterator class(it iterates through Windows processes) can't ever be copy-constructible or copy-assignable - it holds a HANDLE
to snapshot and manages freeing it so it's impossible to copy those - moving them is possible, I supplied a move constructor and move assignment operator. However, algorithm std::find_if
copies them(in VC++ 14.0 is calls some std::_Find_if
which requires copying the iterator) and doesn't want to work.
Why does your iterator hold on to a resource? An iterator should be like a pointer where it points to something.
Because in order to iterate through Windows processes, you need to create a snapshot, and then use it to do so - the problem is, one snapshot, one iteration. Also snapshot isn't copyable.
Why can't they just be MoveConstructible
and MoveAssignable
? Which algorithms(if any) truly need copying iterators to work?
Upvotes: 7
Views: 874
Reputation: 6440
TL;DR: Due to historical reasons.
I think, it's more or less obvious why ForwardIterator
and other more functional iterators need to be copyable. As for InputIterator
and OutputIterator
, the situation is a bit more complicated.
The InputIterator
and OutputIterator
have one-pass nature which coincides perfectly well with the move-only class concept. Now, when you use any of these iterators from the standard library (let's say it's istream_iterator
for example), you may copy it and dereference the copy, but advancement of any of the copies would advance all of them, which does not look like an expected behavior.
Unfortunately, at the moment of writing many of the STL algorithms (like std::find_if
, std::copy
, etc) there were no move semantics at all, and there was no way of requiring the InputIterator
to be move-constructible.
Since then, on some platforms STL algorithms actually require the iterator given to be copyable (like in this case), and on other platforms (like g++ AFAIK) this behavior is required by the concept of InputIterator
which is checked in compile time each time you use STL algorithms.
Also, you may find this answer useful.
Upvotes: 3
Reputation: 137310
Iterators should not hold resources; they are abstractions of pointers, and should be cheap to copy. The entire standard library assumes this.
Use a separate (move-only) class to manage the HANDLE
; your iterators should store a pointer to that class.
Upvotes: 3
Reputation: 62563
Well, how can they be not? Simplest possible find would look something like it:
for (IT i = begin_iterator, e = end_iterator; i != e; ++i)
And how would it construct i?
Upvotes: -2