
On Sat, Nov 22, 2008 at 12:13, Mathias Gaunard <mathias.gaunard@ens-lyon.org> 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@ens-lyon.org> 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?