Johan Engblom
Johan Engblom

Reputation: 215

How do I properly check that a istreambuf_iterator has reached end-of-stream

In the standard I read that you have to create a deafult iterator to be able to know if the iterator has reach end-of stream. I think it's getting quite ugly, isn't there any predefined symbol or equivalent that could help us here?

The default-constructed std::istreambuf_iterator is known as the end-of-stream iterator. When a valid std::istreambuf_iterator reaches the end of the underlying stream, it becomes equal to the end-of-stream iterator.

Here is code example:

std::istreambuf_iterator<char> it(is);
std::istreambuf_iterator<char> end;

    if (it != end) { break;}

Why doesn't the iterator has a function named, i.e. hasNext() or isEndOfStream()

Upvotes: 1

Views: 984

Answers (1)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385274

isn't there any predefined symbol or equivalent that could help us here?

Yes.

you have to create a deafult iterator to be able to know if the iterator has reach end-of stream

Here it is!

Why doesn't the iterator has a function named, i.e. hasNext() or isEndOfStream()

The singular iterator as sentinel is actually quite elegant. It doesn't introduce any new names into the library, and it allows us to write generic code with start and end iterators that doesn't care what kind of thing you're iterating over. That's really important for the standard algorithms.

void bar(const char c);

template <typename Iterator>
void foo(Iterator start, Iterator end)
{
   for (Iterator it = start; it != end; ++it)
      bar(*it);
}

void version_1()
{
   std::istreambuf_iterator<char> start(std::cin);
   std::istreambuf_iterator<char> end;
   foo(start, end);
}

void version_2()
{
   std::vector<char> v{0,1,2,3,4,5};
   foo(v.begin(), v.end());
}

Imagine if for containers you had start and end, but for streams you had start and a call to start.hasNext()? Now, that's not very elegant. That's messy!

Upvotes: 3

Related Questions