Boost logo

Boost :

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


On Sat, Nov 22, 2008 at 13:12, Tomas Puverle
<Tomas.Puverle_at_[hidden]> wrote:
>
>> But what semantics for empty *are* documented?
>>
>> http://www.boost.org/doc/libs/1_37_0/libs/range/doc/boost_range.html
>> empty(x) returns boost::begin(x) == boost::end(x)
>
> Prior to 1.35, the iterator_range<> documentation read the following:
>
> "Recall that many default constructed iterators are singular and hence can only
> be assigned, but not compared or incremented or anything. However, if one
> creates a default constructed iterator_range, then one can still call all its
> member functions. This means that the iterator_range will still be usable in
> many contexts even though the iterators underneath are not. "
>
> Does this answer your question?
>

Thank you; I hadn't noticed that.

However, the documentation for both says that "The intention of the
iterator_range class is to encapsulate two iterators so they fulfill
the Forward Range concept," given a template argument that matches the
ForwardTraversalIterator concept.

The problem, then, is that neither the 1.34 nor 1.35 implementation
satisfies the requirements for the Forward Range concept given an
iterator such as the following, despite it being, as far as I can
tell, a perfectly legal Forward Traversal Iterator:

template <typename T>
struct contrived_iterator {
    shared_ptr<T> x;
    bool dirty;

    contrived_iterator() : x(new T()), dirty() {}
    contrived_iterator(contrived_iterator const &i) : x(i.x), dirty(i.dirty) {}
    contrived_iterator &operator=(contrived_iterator const &i) { x =
i.x; dirty = i.dirty; }

    contrived_iterator &operator++() { dirty = true; }
    contrived_iterator operator++(int) { contrived_iterator i = *this;
++*this; return i; }

    bool operator==(contrived_iterator i) { return dirty || i.dirty; }
    bool operator!=(contrived_iterator i) { return !(*this == i); }

    T &operator*() { return *x; }
    T const &operator*() { return *x; }

    typedef int difference_type;
    typedef T value_type
    typedef T& reference;
}

template <typename T>
struct iterator_traversal<contrived_iterator<T> > {
    typedef forward_traversal_tag type;
}

It seems there's an assumption that a default-constructed iterator is
either singular or past-the-end, but I saw no such requirement in
either the standard or the "New iterator concepts" document.


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