Search code examples
c++c++20stringstreamistringstream

Is std::istringstream::peek() supposed to set the eof flag?


Consider the following code:

#include <iostream>
#include <sstream>

void print_flags(std::istringstream & iss)
{
   std::cout << "good: " << iss.good() << ", eof: " << iss.eof() << ", fail: " << iss.fail() << ", bad: " << iss.bad() << "\n";
}

int main()
{
    std::istringstream iss("A");
    char chr;
    iss >> chr;
    print_flags(iss);
    iss.peek();
    print_flags(iss);
}

On both g++ and clang++ I see the following output:

good: 1, eof: 0, fail: 0, bad: 0
good: 0, eof: 1, fail: 0, bad: 0

The cppreference article does not mention that peek modifies the flags. It mentions the flags being modified by get: cppreference.

Is this behaviour correct with regards to the standard?


Solution

  • Yes, it's a requirement on UnformattedInputFunction.

    First, description of peek (emphasis mine):

    Effects: Behaves as an unformatted input function (as described above). After constructing a sentry object, reads but does not extract the current input character.
    Returns: traits​::​eof() if good() is false. Otherwise, returns rdbuf()->sgetc().

    Then, from description of UnformattedInputFunction above (emphasis mine):

    [...] If rdbuf()->sbumpc() or rdbuf()->sgetc() returns traits​::​eof(), then ios_base​::​eofbit is set in the local error state and the input function stops trying to obtain the requested input. [...]