Search code examples
c++istreamlibc++

Shouldn't istream::peek() always return what you just putback()?


Intuitively, judging from the C++ spec, it looks to me as if istream::putback( c ) should always arrange the input buffer such that the next call to istream::peek() should read the character c. Is this not correct? I ask because the latest version of libc++ shipping with Xcode 4.6 seems not to enforce this behavior in all cases—particularly when the last character is at the EOF. The same is true if you use unget() instead of putback( c ).

Is libc++'s behavior correct, or is my intuition of how putback()/unget() should work correct?

Consider this example code, which works with libstdc++ but not with libc++ (the assertion fails).

#include <sstream>
#include <cassert>

int main(int argc, const char * argv[])
{
    std::istringstream in( "[Test]" );

    while( in )
    {
        int c = in.get();
        if( c == ']' )
        {
            in.putback( c );
            assert( in.peek() == c );   // Fails with libc++. Succeeds with libstdc++.
            break;
        }
    }

    return 0;
}

Solution

  • There has actually been a change to the putback function in C++11:

    §27.7.2.3/34

    basic_istream<charT,traits>& putback(char_type c);

    Effects: Behaves as an unformatted input function (as described in 27.7.2.3, paragraph 1), except that the function first clears eofbit. ...

    Where the second half of the sentence didn't exist in C++03.

    So it might depend on whether the compilers have fully implemented this change, or if you use the required options (-std=C++11?).