Boost logo

Boost :

From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2001-07-28 15:12:26


 Fernando Cacciola wrote:
> > 1. Would it make sense to make versions of all the
> > algorithms working on containers, not iterators pair.
> >
> Why do you need this functionality?
> Consider that an algorithm taking a range can always be called with
> (c.begin(),c.end()); whereas an algorithm taking a container cannot be
> called with a range (not without a range_view). From the
> algorithm point of view, the range based interface is more flexible.

Sure, the problem is that the standard library does not support that
interface very well (BTW, see
http://groups.yahoo.com/group/boost/message/5178 thread for a previous
discussion on the topic). For example, suppose that, in the true spirit of
STL <g>, I have a (global) 'selection' function that returns a std::pair
(ick!) of iterators to, let's say, some 'record' objects, and I want to
store these selected record objects in std::vector<record>. How would you
write this? Probably something like the following:

// hypothetical 'selection' function
std::pair< any_iterator<record>, any_iterator<record> > selection();

// code that stores selection in vector
std::pair< any_iterator<record>, any_iterator<record> > sel = selection();
std::vector<record> v(sel.first, sel.second);

Don't you think that this is unnecessary ugly and awkward? I do, and typedef
for "std::pair< any_iterator<record>, any_iterator<record> >" doesn't change
much here. There are several things that I don't like about the above code:

1) repeating the type of iterator twice (std::pair<Iterator, Iterator>) is
silly and tedious;
2) what I really want to write is std::iterator_range<Iterator>, and writing
std::pair<Iterator, Iterator> instead obscures the intent and expressiveness
of the code;
3) temporary 'sel' variable is unnecessary and ugly; I would like to be able
to write std::vector<record> v(selection());
4) temporary 'sel' variable introduces unnecessary overhead of copying two
'any_iterator' objects, and in general it's quite an expensive operation;
5) things get worse if you consider "chaining" of functions that take
"formless" iterator ranges, e.g.

std::pair< any_iterator<record>, any_iterator<record> > sel = selection();
std::pair< any_iterator<record>, any_iterator<record> > mismatching_part =
std::mismatch(sel.first, sel.second, old_selection.begin());
std::vector<record> v(mismatching_part.first, mismatching_part.second);

This is already too much; well, actually, it's not anymore a problem for me
:), because we don't write the code like the above; instead, we write:

mtn::vector<record> v(
    mtn::mismatch(selection(), mtn::begin(old_selection))
   );

but there are probably a few other programmers out there that would like to
feel the same :).

Aleksey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk