Boost logo

Boost :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2004-04-23 00:51:34


David Abrahams wrote:

>> I see that std::input_iterator requirements say that after ++r any
>> copies of the previous value of r are no longer required to be
>> dereferencable.
>
> Right. That rules out your scenario of keeping old copies of the
> iterator around and derferencing them later.

True. I did not see that clause until yesterday.

>> New iterators requirents are silent on this. Is this intentional?
>
> Probably not. However, if the standard doesn't explicitly guarantee
> iterator stability, you can't count on it. That said, a note would
> probably be good to add.

Okay. BTW, what guarantees that ++r does not invalidate any copies for
forward/bidirectional/random iterator?

>> If single pass iterator requirements
> ^^...
>> - would add the same note about ++r making iterators dereferencable
> "non-"----------^
> Probably a good idea.
>
>> - retain the same requirements for operator++(int)
>
> Really you mean requirements on the expression "*r++", I think.

No, on operator++(int)

> ...then what?
>
>> The result of r++ is not required even to be dereferencable
>
> Not required by which concept?

By nothing I could find in new iterator requirements. Requirements on
operator++(int) say:

   {
       X tmp = r;
       ++r;
       return tmp;
   }

operator++ is allowed to invalidate 'tmp', and nothing explicitly requires
return value from operator++(int) to be dereferencable.

>> The solutions I see are:
>>
>> 1) require that ++r does not makes any copies dereferencable, or
>
> I think you mean "not require that any copies are dereferencable after
> "++r"?

Nope, I meant what written. If ++r is required to keep the copies
deferencable then *r++ will be guaranteed to work. OTOH, this would require
storing value in iterator which as you say is not indented by current
input_iterator.

>> 2) allow returning proxy from operator++(int)
>
> That doesn't allow all readable single-pass iterators to be input
> iterators. I'm against it.

It's possible to require that return value from operator++(int) is some type
with operator* and application of operator* returns the same value as the
*it before incrementing.

> What would the proxy do, anyway?

Here's commented out code in filesystem lib:

      struct path_proxy // allows *r++ to work, as required by 24.1.1
      {
        path pv;
        explicit path_proxy( const path & p ) : pv(p) {}
        path operator*() const { return pv; }
      };

      path_proxy operator++(int)
      {
        path_proxy pp( m_deref() );
        ++*this;
        return pp;
      }

>> 3) require that result of r++ is dereferencable and is equivivalent to
>> the dereferencing of the previous value of 'r'.
>
> I think we need want 1&3.

Will 3) require extra storage in iterator? Now, transform_iterator can store
only wrapped iterator and a functor. If 3) is required it should
additionally store either value, or a flag telling there's a undereferenced
copy (as you've suggested). Besides, In the second case it should be stated
that return of r++ is dereferencable untill you call operator*() or
operator++() on original iterator.

> > The variant 2) would be most convenient for directory_iterator...

> Yeah, but it would break interoperability with old algorithms.

Why? Input iterator requirements only say that *r++ should return T. They
don't say anything about type of r++.

- Volodya

Yeah, but it would break interoperability with old algorithms.


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