Boost logo

Boost :

Subject: Re: [boost] Is Boost.Range broken?
From: Scott McMurray (me22.ca+boost_at_[hidden])
Date: 2008-11-22 12:56:19


On Sat, Nov 22, 2008 at 12:13, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
>
> iterator_range being a generic tool, it wants to maintain the invariants
> which are necessary to make it work whatever its parameters are, even if
> those invariants happen not to be necessary for some parameters.
>

I'm not that much of a fan of the invariant, though, since the
problematic values are undetectable and the approximation has both
false negatives and false positives. The invariants can be checked
reliably at the iterator level -- and are, with iterator debugging
enabled -- which seems sufficient to me.

On Sat, Nov 22, 2008 at 12:20, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
> Scott McMurray wrote:
>
>> Also, what if I write a random_number_iterator, a forward iterator
>> which returns a different random number after each increment? Then
>> iterator_range<random_number_iterator>() is again non-singular, and it
>> has an infinite size (operator== would always be false)
>
> In that case, it might be clearer to write something like
>
> iterator_range<random_number_iterator> r(random_number_iterator(),
> random_number_iterator());
>
> Here, it is explicitly initialized and thus iterator_range should know that
> this is not a singular range.
>
> That is quite a pain, of course.
>
>> , so the
>> empty() for the range should *not* return false.
>
> I'm not sure I'm following.
> The way you wrote it, it should abort, and the way I wrote it, it should
> return false.
>

I meant "should not" as in "inconsistent with what the iterators would
say", but you're right, I was relying on implementation detail rather
than documented behaviour.

Having a default-constructed iterator_range not be useful as anything
other than the lhs of an assignment does seem reasonable, but I can't
see any justification for making iterator_range<I>() any different
from iterator_range<I>(I(), I()), since it's neither POD nor
aggregate. Similarly, pair<A,B>() is specified as "Initializes its
members as if implemented: pair() : first(T1()), second(T2()) {}",
giving it the same value as pair<A,B>(A(), B()). (Not explicitly
initializing the members seems without gain, since initializing a POD
has trivial cost, and everything else will get constructed anyways.)

Changing tacks slightly, has anyone yet elaborated the use case for
the old behaviour? A default-constructed container is useful because
you can add elements to it, but since a default-constructed iterator
range can never be manipulated in a useful fashion, why would someone
ever want to pass or store it at all?


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