Mihai Todor
Mihai Todor

Reputation: 8249

streambuf, ostream, ostreambuf, istream, istreambuf and associated iterators

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, string_iterator (std::string::iterator and std::string::const_iterator do exist) or 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

Answers (3)

Benjamin Lindley
Benjamin Lindley

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

Loki Astari
Loki Astari

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

DanielKO
DanielKO

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

Related Questions