
This is a subject in which I've had some interest. In my case this resulted in the "dataflow iterator" part of the serialization library. I've just looked at the documention referred to below rather than the code. Still, I have some questions: Its not clear to me what the benefit of using ranges is compared to a pair of iterators. "John Torjo" <john.lists@torjo.com> wrote in message news:418F4161.7050202@torjo.com...
It makes dealing with containers/STL algorithms simpler by using ranges (as opposed to iterators).
for ( crange<some_array_type> r(some_array); r; ++r) do_something( *r, some_data);
How is this simpler or more transparent than for(some_array::iterator i=some_array.begin(); i != some_array.end(); ++i) do_something( *i, some_data);
Also, the library provides wrappers for all STL algorithms (for the purpose of STL algorithms, all containers are ranges as well):
typedef std::vector<std::string> word_array; word_array v; // STL version std::copy( v.begin(), v.end(), print); // rng:: version rng::copy( v, print);
I don't see this as adding any value or conceptual transparency.
Also, the counterparts for STL algorithms that return an iterator will return a range, allowing for: // fill a vector with all the indexes at which a certain string is found std::string str = "I'm a cool programmer, really cool that is", find = "cool"; std::vector<int> result; crange<std::string> r(str); while ( r = rng::search(r, find)) result.push_back ( r.begin() - str.begin() );
I'm not really sure that I understand this example. It would seem the standard stl equivalent would be std::vector<int> result; std::string str = "I'm a cool programmer, really cool that is"; std::string find = "cool"; std::string::const_iterator r = str.begin(); while(r = stl::search(r, find.begin(), find.end())) result.push_back ( r.begin() - str.begin() ); which to my mind isn't any different or more complex.
And it provides for range adaptors, allowing for composition.
bool from_ro(const employee & e) { return e.country == "Romania"; } std::string get_empl_name(const employee &e) { return e.name; }
typedef std::vector<employee> array; array empls;
// take all employees from Romania, and print their names rng::copy( transformed( filtered(empls,from_ro), get_empl_name), std::ostream_iterator<std::string>(std::cout," "));
I don't see how this is better than using iterator adaptors for composition. The Dataflow Iterators part of the serialization library includes examples such as: typedef typedef insert_linebreaks< // insert line breaks every 72 characters base64_from_binary< // convert binary values ot base64 characters transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes const char *, 6, 8 > > ,72 > base64_text; // compose all the above operations in to a new iterator std::copy( base64_text(address), base64_text(address + count), ostream_iterator<CharType>(os) ); It would seem that ranges could only applied to forward iterators - excluding the usage of input iterators. It would also exclude transformations that don't create an intermediate temporary container. E.G. zip transform (similar to a unix paste command) which merges two iterator adaptors into one. Basically, this seems to me an extra layer that doesn't add any new concept or make things more transparent. I will concede that it might save a tiny bit of typing. I've used the Dataflow Iterators to contrast mainly because I wrote it and am familiar with it. I'm aware of a number of other similar efforts. When faced with this problem, I did consider development of the concept of ranges. After looking around and experimenting with it I concluded that the orginal STL used iterators rather than ranges for a reason - and a good one at that. Robert Ramey