The iterator is expected to give a reference to a value, but that doesn't prevent it from managing that same value.
Consider the alternatives (1, 2):
1) So far I have found the functor interface the easiest to implement. A code using a functor might look like
auto images = Image::all(); while (auto image = images()) {image->doSomething();}
where Image::all
returns std::function<boost::optional<Image>()>
implemented by either a functor class or a lambda.
2) Rook's idea of using a stream looks really nice and idiomatic. Might look like
Images images; Image image; while (images >> image) {image.doSomething();}
where operator >>
returns Images&
, its operator bool()
returning false when the stream is finished.
3) But I see the iterators used for that kind of thing all the time, like the recursive_directory_iterator. And the reason for this is the reuse of the generic algorithms, like std::find
and std::copy
. Imagine using std::copy
to create a backup of your images:
std::copy (images.begin(), images.end(), backup.begin());
This is very succint, idiomatic and follows the principle of least astonishment.
I would say it's your choice, as a developer, whether to use a functor (aka generator), a stream, iterators or something else, but the iterators approach is usually the most friendly towards the users of your API.