Topic: Definition of input iterators


Author: James Kuyper <kuyper@wizard.net>
Date: Fri, 5 Jan 2001 00:58:43 GMT
Raw View
Hubert Matthews wrote:
>
> I've found what I consider to be a problem with the definition of input
> iterators in the Standard.  Table 72 states that incrementing an
> iterator (using either prefix or postfix ++) may invalidate any copies
> of that iterator.  This is a problem when implementing operator++(int),
> as it must return a copy of the pre-increment value of the iterator
> which may now not be dereferenceable because of the increment.

You're missing the point - that returned value is the only one that IS
dereferenceable. It didn't exist yet at that the time the operator++()
was executed, and is therefore not at risk. How that's handled
internally by the iterator is up to the creator of the iterator class -
it might involve making copies that in user code would be risky -
however, all the risk is the creator's responsibility. What table 72 is
saying is that the creator is free to invalidate any iterator other than
the one that is returned.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Hubert Matthews <hubert@oxyware.com>
Date: Fri, 29 Dec 2000 01:18:02 GMT
Raw View
I've found what I consider to be a problem with the definition of input
iterators in the Standard.  Table 72 states that incrementing an
iterator (using either prefix or postfix ++) may invalidate any copies
of that iterator.  This is a problem when implementing operator++(int),
as it must return a copy of the pre-increment value of the iterator
which may now not be dereferenceable because of the increment.

Table 72 defines the effect of *r++ to be { T tmp = *r; r++; return tmp;
}.  How is this to be achieved with a user-defined iterator since *r++
must, by the rules of operator precendence, be evaluated as
operator++(int) followed by applying operator*() to a potentially
invalidated iterator?

My suggestion is that incrementing an iterator should guarantee that
copies of that iterator are still dereferenceable but not necessarily
incrementable.  This allows the return from operator++(int) to be used
safely.

Any takers, or am I being overly fussy?

Hubert

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Tue, 2 Jan 2001 01:56:06 GMT
Raw View
On Fri, 29 Dec 2000 01:18:02 GMT, Hubert Matthews <hubert@oxyware.com>
wrote:

> I've found what I consider to be a problem with the definition of input
> iterators in the Standard.  Table 72 states that incrementing an
> iterator (using either prefix or postfix ++) may invalidate any copies
> of that iterator.

I says may not must.  I think you may be misreading the iterator
requirements.  These are the minimum requirements for a thing to
claim that it is an input iterator.  That places a restriction on
the operations which an algorithm may perform when it claims to
support an input iterator.  It does not restrict what an input
iterator is allowed to do.

> This is a problem when implementing operator++(int),
> as it must return a copy of the pre-increment value of the iterator
> which may now not be dereferenceable because of the increment.

No, operator++(int) is not required to return the pre-increment value.
It is required to have the same side effect as operator++() and the
return is not usable in general.

> Table 72 defines the effect of *r++ to be { T tmp = *r; r++; return tmp;
> }.  How is this to be achieved with a user-defined iterator since *r++
> must, by the rules of operator precendence, be evaluated as
> operator++(int) followed by applying operator*() to a potentially
> invalidated iterator?

No.  Istream_iterator is a std example which returns an iterator
which has not been invalidated.  Knowing that istream_iterator does
not invalidate copies allows me to store them in a vector and sort
them and then copy the results.  However, I can not write a general
algorithm which claims to use input iterators to do this.
Istreambuf_iterator is a std example which returns a proxy with an
operator* which allows *r++ to work when the iterator is invalidated.
These are both examples only, not requirements for implementation.
They will both work with any algorithm which uses only those operations
required for input iterators.

> My suggestion is that incrementing an iterator should guarantee that
> copies of that iterator are still dereferenceable but not necessarily
> incrementable.  This allows the return from operator++(int) to be used
> safely.

The only thing that is allowed is *r++.  All that an implementer needs
to do is make that work.  It is safe to use the return from
operator++(int) in the one allowed operation for all std input
iterators.  When creating a new input iterator, make it work.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]