Boost logo

Boost :

From: brangdon_at_[hidden]
Date: 2001-12-24 13:59:13


In-Reply-To: <000c01c18c0d$29fe26f0$a65ea240_at_[hidden]>
On Sun, 23 Dec 2001 15:54:30 -0800 James Mitchell (jimdesu_at_[hidden])
wrote:
> So far as operator overloading goes for a range, I think it's important
> to overload at least the increment and decrement operators because they
> provide pre- and post- semantics.

My personal view is that post- semantics are so rarely needed they need
not be supported.

> I dislike the pop_front() and pop_back() because that becomes
> too container-like for my tastes.

I felt they were the clearest, most obvious names for what they did. Using
a common terminology with containers seemed like a virtue. But then I see
the semantics as being the same in both cases...

> It also implies that you can shorten a range but not extend it,
> although that might be a matter of interpretation.

I did indeed intend that ranges be shortened but not extended. I feel this
is more robust. Making a non-empty range shorter is always a safe
operation. Making it bigger is safe only if we do not make it bigger than
its underlying container. That is a hard thing to tell by inspecting the
code. Even enforcing it with assertions can mean carrying more data
around.

I see this constraint as part of the extra value offered by ranges over
plain iterators, part of what I mean when I say they are higher level
objects.

> I definitely want to support both recursive and procedural
> styles, [...]

Me too. I don't see a problem.

> [...] and pop_front() & pop_back() raise the question: "are the
> prior(last) elements still in the range?".

They are not. That is why I see them as similar to the container
operations. The elements might not actually be destroyed by the operation,
but as far as this range is concerned they have become inaccessible.

We can make a copy of the range before popping it, if necessary. If we
need to do a lot of to-ing and fro-ing, maybe the algorithm is more suited
to iterators anyway?

> I also think the pointer-like semantics make more sense with
> generators and filters: by keeping with such, you could potentially pass
> back to the user a functor of type range<char> returning {'a',...,'z'}
> or somesuch, which would work automagically with the operators, but not
> with other functions.

Are you suggesting that a range be a model of the iterator concept? I
think that is trying to make them be too many things at once.

One potential problem is that operator*() can reasonably get the element
at either end. Consider code like:

    template <typename Range>
    void reverse( Range r ) {
        while (r.size() > 1) {
            swap( r.front(), r.back() );
            r.pop_front();
            r.pop_back();
        }
    }

I don't think operator overloading scales to bi-directional ranges, and I
don't want to make too much of a special case for forward-ranges. If you
want an iterator, use an iterator - r.begin() will probably do.

> (Of course, operator*() would break, but in that case you
> should know better than to use it!)

Why would it break? I hope my r.front() won't break in code like
reverse(). It should be an l-value that we can assign to.

> Granted that I've only skimmed the articles to which you and
> Darin have pointed me(xmas things getting in the way of coding-related
> stuff!), so this may have been all hashed out already.

Not really. Nobody other than me has been in favour of increment/decrement
on ranges at all, so there hasn't been much discussion of what form they
should take.

-- Dave Harris


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