Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-04-21 06:39:40

Vladimir Prus <ghost_at_[hidden]> writes:

> There's a bug report on sourceforge:
> which boils down to the fact that
> directory_iterator it(...);
> path p = *it++;
> does not work correctly. The exact problem is that the above line return a
> copy of the iterator, and increments 'it', but both iterators have shared_ptr
> to the same internal structure, so by time user deferences the copy, it gets
> the next file in the directory.
> The filesystem lib sources contain the following comment:
> The *r++ requirement doesn't appear to apply to the new
> single_pass_traversal category
> Thus I'm leaving the proxy out pending confirmation from the N1477
> authors

I'm kinda surprised that nobody asked us about that problem; we can't
confirm something we don't know about!

> I'm not sure I understand that. It seems that *r++ should work,
> since signle pass iterator requires that r++ should work and return
> object of type X (call it r2), and the reabable iterator requires
> that *r2 should work. Am I wrong?

The question is, what are the semantics?

Input iterator requirements say:

    Expression Type Semantics
    ---------- ---- ------------------------------
    (void)r++ equivalent to (void)++r
    *r++ T { T tmp = *r; ++r; return tmp; }

But we don't have anything similar in the new concepts. I guess
that's because we're trying to orthogonalize access and traversal, but
that may not be possible in this case. If we don't define the
semantics of *r++, a single-pass iterator is free to implement the
semantics of *r++ as equivalent to *++r, which is what
directory_iterator is doing.

I'm sure directory_iterator is reporting that its category is
input_iterator_tag, so I guess we have a problem in the new iterator
concepts and in the iterator_facade implementation here.

> And BTW, don't the above requirements

Which ones?

> mean r++ cannot return a proxy object, but only a real copy of the
> iterator?

The input iterator requirements seem to imply that, for true
single-pass sequences like streams, either:

a. the iterator can store a copy of its value_type so that the
    iterator returned from r++ can still return the 'tmp' value
    indicated above when dereferenced

b. the iterator can track whether an iterator returned from a
    post-increment is "active and not yet dereferenced"

case b. is interesting; it would mean that operator++(int) can set a
flag telling the iterator to consume another value before

Dave Abrahams
Boost Consulting

Boost list run by bdawes at, gregod at, cpdaniel at, john at