
"Robert Ramey" <ramey@rrsd.com> wrote in message news:cmrl55$hng$1@sea.gmane.org...
"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:cmrk1g$f70$1@sea.gmane.org...
Here's my general take on it: iterators are important and useful as the lower-level infrastructure. iterators are, however, not too user-friendly; the user-friendly interface can be build on top so easy task becomes , well, easy. and that is the purpose of ranges and johns range library. without a good iterator library underneith ranges where hard to craft, but now that we have a good iterator library, we should persue higher abstractions
I agree that iterators aren't that easy or intuitive to work with. So our motivations have much in common. My view is that iterators can be made easier to work with without changing their fundamental character and without the need to introduce what I see as a new concept (ranges) that is "almost the same" as an existing concept - pair of iterators.
Robert Ramey
While iterators are very good at what they do -- provide access to elements in a sequence -- they do not capture the concept of a sequence very well. If I want to access a sequence of elements, I'd like to see a clean front-end, and I believe that John's range library can provide me with such a clean front-end. Using for_each(s.begin(), s.end(), ...) is too low-level, it exposes details of a sequence that I do not want to know. I do not want to for_each on a begin and an end, I want to for_each on a sequence: for_each(s, ...). It's a conceptual layer, admittedly a small one, but it provides a great front-end for the back-end of iterators. std::pair<iterator, iterator> fails at creating a decent front-end. For one thing, the iterator type must by typed twice. This adds quite some text. Secondly, it stays in the 'begin-end' concept, instead of advancing to a real range, of which you can extract an element and advance to the next by shrinking the range. You said before that the STL had a very good reason to use iterators. I agree there, iterators are very effective at what they do, but I'd like a higher-level interface built on top of that. For me, the following example from the Range Adaptors and Composition(s) documentation illustrates that: // [1] print all even elements (not using range adaptors) typedef boost::filter_iterator<array> filter_iterator; rng::for_each( irange<filter_iterator>( filter_iterator(some_array.begin(), is_even), filter_iterator( some_array.end(), is_even), print ); // [2] print all even elements (using range adaptors) rng::for_each( filtered(some_array, is_even), print); [1], while already using ranges, is easily rewritten to an iterator-only version. In [1], two iterators have to be wrapped with a filter_iterator constructor, both containing the same predicate. In [2], a range adaptor is used, and the predicate need only be given once. When I read the second version aloud, I hear exactly what I want to hear: "Take the elements of some_array, filter out the even elements, and print them". With [1], it's much more difficult to read it aloud. It also contains redundancy: is_even is passed twice. While possibly even error-prone, I think this is just ugly. It's not filter_iterator's fault, the filter_iterator is great at what it does, but it is the range adaptor that wraps it up nicely and provides a clean interface to ranges, not just begin-end pairs. best regards, Richard Peters