c++stdstringistreamistream-iteratorinput-iterator

Can I use istream_iterator<char> to copy some istream content into std::string?


I have an istream and need to copy the content between two delimiters to a std::string. I can find the delimiters' streampos, but when trying to use istream_iterator<char> to iterate over the section of the stream, it does not work. Here's what I tried:

#include <iostream>
#include <sstream>
#include <iterator>


std::string copyToString( std::istream& is )
{
    is >> std::ws;

    auto someLength {10};

    std::istream_iterator<char> beg {is};

    is.seekg( someLength, std::ios::cur );

    //std::istream_iterator<char> end { is };
    std::istream_iterator<char> end { std::next(beg, someLength) };

    return std::string{ beg, end };
}




int main()
{
    std::stringstream ss;
    ss.str( "   { my string content  }" );

    std::cout << "\"" << copyToString( ss ) << "\"\n";

    return 0;
}

I expected the output to be 10 chars long, but it's just "{". If I uncomment the line std::istream_iterator<char> end { is }; and comment out the next one, the output is just "".

What am I missing? Can I not use iterators like that?

I am aware that I could create a char[] as a buffer, copy it to that, etc., but that seems much less straightforward.


Solution

  • std::istream_iterator is an input iterator. Input iterators are single pass and are invalidated when copies thereof are incremented. When you do std::next(beg, someLength), you read someLength characters. Then beg is invalidated.

    Moreover, std::istream_iterator is not intended to be counted. It is designed to be compared to a default constructed iterator, because of the way stream errors are handled. If you attempt count them, then they will sometimes read one more time, depending on how the algorithm is implemented.

    If you want to read n characters from an input stream, just use read. If you want to skip spaces, then just write a loop. If you want to use std::istream_iterator in an unintended way, then your code will fail unpredictably.