views:

123

answers:

4

Hi, I'm trying to initialize string with iterators and something like this works:

ifstream fin("tmp.txt");  
istream_iterator<char> in_i(fin), eos; 
//here eos is 1 over the end  
string s(in_i, eos);

but this doesn't:

ifstream fin("tmp.txt");
istream_iterator<char> in_i(fin), eos(fin);
/* here eos is at this same position as in_i*/
//moving eos forward 
for (int i = 0; i < 20; ++i)
{
    ++eos; 
}
// trying to initialize string with 
// pair of iterators gives me "" 
// result  
string s(in_i, eos);

Thank you.

+2  A: 

I don't think you can advance the end iterator to a suitable position: to advance the iterator means to read input, also both iterators are referencing the same stream - therefore advancing one iterator means to advance the second. They both end up referencing the same position in the stream.

Unless you are willing to write or find an iterator adaptor (boost?) that does an operation on n items referenced by some iterator, it might not be possible to initialize the string like that. Or you read the value with other methods and set the value of the string later.

UncleBens
The key phrase is "input iterator". I added reference to iterator classification article.
Roman Nikitchenko
Boost.Spirit defines a MultiPass iterator converting an input interator into a forward iterator: http://www.boost.org/doc/libs/1_40_0/libs/spirit/classic/doc/multi_pass.html.
Éric Malenfant
+1  A: 

istream_iterator is input so your second code fragment isn't correct, you can't do this (second pass). Please look here and pay attention to "single pass" algorithms support (second paragraph under "description" title). First fragment doesn't try to perform 2 passes.

Is this explanation OK? BTW SGI STL reference (from where I posted link) is somewhat outdated but very usable for some quick references (by my opinion). I'd recommend it to be bookmarked.

Roman Nikitchenko
+1  A: 

The istream_iterator is a very limited iterator knows as a input iterator.

See: http://www.sgi.com/tech/stl/InputIterator.html

But basically for input iterators very few gurantees are made.
Specifically to your case:

i == j does not imply ++i == ++j.

So your first example is an iterator that is passed the end of stream. It is valid (as long as it is not incremented) and comparable to other iterators so works for reading the whole stream.

Martin York
A: 

From the standard [24.5.1]/1:

[...] The constructor with no arguments istream_iterator() always constructs an end of stream input iterator object, which is the only legitimate iterator to be used for the end condition. [...] The main peculiarity of the istream iterators is the fact that ++ operators are not equality preserving, that is, i == j does not guarantee at all that ++i == ++j. Every time ++ is used a new value is read.

[24.5.1]/3

Two end-of-stream iterators are always equal. An end-of-stream iterator is not equal to a non-end-of-stream iterator. Two non-end-of-stream iterators are equal when they are constructed from the same stream

The first paragraph states that you cannot use any but end-of-stream iterators as end conditions, so your first usage is correct and expected. The third paragraph in the chapter states that any two non-end-of-stream iterators into the same stream are guaranteed to be equal at all times. That is, the second usage is correct from the language standpoint and will provide the results you are getting.

The last part of paragraph 1, where it states that i == j does not imply ++i == ++j deals with the particular case of one last element present in the stream. After incrementing the first of the iterators (either i or j) the datum is consumed by that iterator. Advancing the other iterator will hit the end of stream and thus the two iterators will differ. In all other cases (there is more than one datum left in the stream), ++i == ++j.

Also note that the sentence ++i == ++j executes two mutating operations on the same element (stream) and thus it is not which of the two iterators get the first/second datum in the stream.

David Rodríguez - dribeas