Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-04-23 06:36:06


Vladimir Prus <ghost_at_[hidden]> writes:

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

None, I think.

>>> 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)

What requirements do you mean, specifically?

>> ...then what?

No answer? You started a phrase with if (condition) but there was no
"body", if you will.

>>> 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;
> }

Right. Traversal and access are supposed to be orthogonal.

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

Right. That's why we need to somehow retain the requirements for
*r++.

>>> 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

That's the opposite of what you wrote. "does not makes any copies
dereferencable" means, "doesn't change any copies of r from
non-dereferenceable to dereferenceable."

> 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.

Yes, and it mean that not all readable single-pass iterators are input
iterators, so I'm against it.

>>> 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 applicatqion of operator* returns the
> same value as the *it before incrementing.

Ah, whoops. OK, that solution is compatible with input iterator and
output iterator, so I favor it.

>>> 3) require that result of r++ is dereferencable and is equivivalent to
>>> the dereferencing of the previous value of 'r'.

Well, that requirement is equivalent to input iterator's requirement
on "*r++". The question is, in which concept does that requirement
go? It's neither a pure access nor a pure traversal concept.

>> I think we need want 1&3.

Now 2&3.

> Will 3) require extra storage in iterator?

Not if accompanied by 2.

> 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).

I don't think the flag will work, actually, because of this
requirement on input iterator:

  operation semantics
  --------- -----------------------
  (void)r++ equivalent to (void)++r

> 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++.

You're right. It's 2&3.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

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