|
Boost : |
From: Robert Ramey (ramey_at_[hidden])
Date: 2004-11-08 12:29:37
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_at_[hidden]> wrote in message
news:418F4161.7050202_at_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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk