
John Torjo wrote:
Like Robert I am uncomfortable with a range concept that has iteration capabilities. For one thing, standard containers don't satisfy that concept, and it seems to me that a container ought to be a range without any special adaptation. Furthermore
Well... This was to allow easy manual loops.
I have doubts about how well this "range/iterator" concept maps onto bidirectional and random access. That said...
It maps ok with bidirectional/random access. If an iterator has a given iterator category, the range will preserve it. I have used it in code, and it's quite powerful.
...Perhaps more importantly, iterator interfaces don't lend themselves to functional composition:
ranges::for_each( transformed(filtered(some_array, is_even), _1 / 2) , print);
Try to say *that* with iterators.
Indeed ;)
This is the design approach taken in MPL and Fusion, and it works very well. I am strongly for an algorithm and lazy adapter library based on ranges, and moderately strongly against directly giving ranges any direct iteration capability.
As you probably know, the library is around 1 year old. I've used it heavily on some of my projects, and all I can say is that iteration capability has helped me much.
If you write all your algorithms to a range interface instead of iterator interface, that's a big win when you really want ranges. When you have to manually iterate in a loop, it's a loss. Now you have to say: template<class in_cont, class out_cont> algorithm (in_cont const& in, out_cont & out) { typename boost::range_const_iterator<in_cont>::type i = boost::begin (in); typename boost::range_iterator<out_cont>::type o = boost::begin (out); for (; i != boost::end (in); ++i, ++o) ... In this case, I'd say it's a net loss.