Boost logo

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

> 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 == "Romania"; }
> std::string get_empl_name(const employee &e) { return; }
> 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:


    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 *,
    base64_text; // compose all the above operations in to a new iterator

    base64_text(address + count),

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
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, gregod at, cpdaniel at, john at