Reputation: 8249
I guess somebody had to ask these questions, so please bear with me.
Let's consider the following beasts:
and the following iterators:
Questions:
Why isn't there any iostream_iterator
, streambuf_iterator
, (std::string::iterator and std::string::const_iterator do exist) or string_iterator
stringbuf_iterator
?
Why don't the 4 iterators listed above have a const version like std::vector<T>::const_iterator
?
How are we supposed to iterate over any of those beasts if they don't provide the begin() and end() methods? What is the purpose of the above 4 iterators?
N00b question: Where can I find a good reference that details the logic behind these classes and, also, some decent examples on how to use them?
Hopefully, someone with experience will provide a good answer for the above questions.
PS: Real life situation:
void writeToStream(std::ostream &out);
int main ()
{
std::ostringstream byteStream;
writeToStream(byteStream);
std::string byteString = byteStream.str();
for (unsigned short i = 0; i < byteString.size(); ++i)
{
//do something with each byteString[i]
}
return 0;
}
My guess is that I could have used ostream
and iterate over its elements by using an iterator just like for std::vector
, instead of using ostringstream
and the str()
method to convert it to a string
, but I couldn't find any information regarding this.
Upvotes: 2
Views: 2583
Reputation: 103713
Why isn't there any iostream_iterator, streambuf_iterator or stringbuf_iterator?
I don't know. Though I would guess that it's simply because they would be more complicated, and there isn't enough demand for them.
Why don't the 4 iterators listed above have a const version like
std::vector<T>::const_iterator
?
A const input iterator would be rather redundant, you can only read from them anyway, not write to them. A const output iterator would be pointless, as that would destroy it's only purpose, which is to output.
How are we supposed to iterate over any of those beasts if they don't provide the begin() and end() methods? What is the purpose of the above 4 iterators?
By creating the iterators with their respective constructors, e.g.
std::istream_iterator<int> in_begin(std::cin), in_end;
std::ostream_iterator<int> out_begin(std::cout, "\n");
std::copy(in_begin, in_end, out_begin);
Note that the end iterator for istream_iterator
is created by simply passing no arguments to its constructor, and that there is no equivalent to an end()
for an output iterator.
Upvotes: 3
Reputation: 264471
Why isn't there any:
* iostream_iterator
* streambuf_iterator
Don't know. Probably because the semantics would be hard to define when doing both input and output. What do you expect to happen when you go forward and then backwards in a stream with an iterator?
- string_iterator
- stringbuf_iterator?
These are easily covered by the existing iterators:
std::string line; // load line.
std::stringstream linestream(line);
std::istream_iterator<int> lineIterator(linestream);
Why don't the 4 iterators listed above have a const version like std::vector::const_iterator?
Because when you iterate across a stream the state of the stream is changing.
How are we supposed to iterate over any of those beasts if they don't provide the begin() and end() methods? What is the purpose of the above 4 iterators?
Because a stream is usually one direction. You don't iterate from the beginning but rather iterate from the current position in the stream to the end. So you just declare an iterator specifying the stream. The iterator starts at the current position and moves towards the end. You can declare an end of stream iterator by just not spcifying the stream.
std::istream_iterator<int> loop(std::cin);
for(;loop != std::istream_iterator<int>(); ++loop)
{
std::cout << *loop;
}
N00b question: Where can I find a good reference that details the logic behind these classes and, also, some decent examples on how to use them?
Here is a good place.
Do a search for "C++ istream_iterator" you will get a lot of hits.
Hopefully, someone with experience will provide a good answer for the above questions.
Hopefully.
Upvotes: 4
Reputation: 4517
Those stream iterators exist to do the trick of writing to/reading from a stream directly from/to a container using standard algorithms. So instead of writing
for (vector<int>::iterator i=v.begin(); i!=v.end(); ++i)
cout << *i <<"\n";
you can just use std::copy:
copy(v.begin(), v.end(), ostream_iterator(cout, "\n"));
For a reference, check something like this, or TC++PL. IMHO they are a neat trick, but don't really help much, as you have little control over the input/output.
Upvotes: 1