§24.1.1/3 from C++03 Standard reads,
For input iterators, a == b does not imply ++a == ++b. (Equality does not
guarantee the substitution property or
referential transparency.) Algorithms
on input iterators should never
attempt to pass through the same
iterator twice. They should be single
pass algorithms. Value type T is not
required to be an Assignable type
(23.1). These algorithms can be used
with istreams as the source of the
input data through the
istream_iterator class.
I couldn’t understand the bold text in the above quotation. Can anyone help me understanding this?
Also, what does the following statement (italicized text in the above quotation) mean? How is it related to a==b and ++a==++b expressions?
Equality does not
guarantee the substitution property or
referential transparency.
The properties referred to are:
Substitution Property
Referential Transparency
Informally, it means that there is no difference between a value and a reference to this value (thus how the term was coined).
In imperative programming it is a difficult concept to get, because we are used to modify our variables. Rick Hickey (behind Clojure) gives a nice talk about the distinction between Identity and State that may help you. The gist of it is that a variable is an Identity. At any point in time an Identity refers to a State. A State never changes, however an Identity may be altered to refer to another State.
Input Iterators
The substitution property violation is “obvious” here, if we define
F(x)in the above to mean++x, then we have that if input iterators verified the substitution property, the following would holda == b => ++a == ++b.This is not true, however, because incrementing an input iterator may invalidate all other input iterators from the same source. From table 107 in n3290 (page 831, just above the paragraph you quoted):
That is, when we perform
++a, thenbmay become invalid, and therefore++bitself will be undefined behavior.This is a direct violation of
++a == ++b, therefore the substitution property does not hold.The referential transparency is a bit more evident here. If Input Iterators were referentially transparent, it would mean that they would be indifferentiable from the value they point to. Clearly this is not the case, as applying
++does not increment the value, but the iterator.