|
Boost : |
From: Aleksey Gurtovoy (alexy_at_[hidden])
Date: 2000-09-14 05:04:30
David Abrahams (<abrahams_at_[hidden]>) wrote:
> Also, I've been thinking how unweildy it is to write std::pair<T, T> for
> ranges, and how much expressive power is lost by writing "pair" instead of
> "range".
Agree completely. I was going to raise this topic too :).
> Instead, I've been using the appended Range<> template (not
> boost-ified), which I derived from std::pair for some compatibility with
> existing uses of pair as a range. What's really missing from this class
are
> all the operations for union, intersection, containment, etc. I've
> implemented these before, but that code is owned by a previous employer
;(.
>
> Does anyone else think this would be really useful?
I do, Dave. The lack of an appropriate support of iterators' ranges in the
standard library is an old and commonly discussed (e.g. in
comp.lang.c++.moderated newsgroup) issue and IMO it should be solved at last
;).
Iterators' range is one of the key concepts of the STL, "most algorithms are
expressed not in terms of a single iterator but in terms of a range of
iterators" [1], and still the library does not provide any handy mechanism
for representing and manipulating by this abstraction. Actually, this issue
and a more general claim that all iterators' ranges should always be
presented by one, not a pair of objects, are probably the most cited
"faults" of the library. Personally, I don't (fully) agree with the second
one, but I think the first issue is a real one and should be resolved.
Actually in many projects I've seen people are already using some home-grown
solutions around awkward code like
std::find( some_long_container_name.begin(), some_long_container_name.end(),
... );
The simplest (and the most dangerous) way to roll up such expressions is to
define a macro, e.g. something like this:
#define seq( c ) (c).begin(), (c).end()
I don't like it. Another way is to define some sort of 'range' class (or
just to use std::pair<>), but this also requires you to write overloaded
versions of all standard algorithms, which would take a range object as
parameter, unwind it and redirect the call to the standard implementation.
That's a lot of work and a lot of code that you have to write every time you
change a job, so may be Boost should take care of it (or invent something
even better :). And of course 'range' class would be useful on its own.
BTW, Stroustrup's "The C++ PL" (SE, 18.3 Sequences and Containers, p. 512)
identifies the issue too, and also gives a possible solution (which is very
close to Dave's Range class). Just a few citations here:
"It is a good general principle that the most common use of something should
also be the shortest, the easiest to express, and the safest. The standard
library violates this principle in the name of generality... Writing
x.begin(), x.end() to express "all the elements of x" is common, tedious,
and can even be error-prone..." and many other right words and examples. (If
you don't remember that you've read this section and you still don't see the
need for the 'range' class, then you might want to take look at it ;)
--Aleksey
[1] http://www.sgi.com/Technology/STL/Iterators.html
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk