Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 209
OldPeculier Avatar asked Feb 11 '13 19:02

OldPeculier


2 Answers

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?).

like image 60
Bo Persson Avatar answered Sep 20 '22 12:09

Bo Persson


Bo Persson is correct about the standards. You are probably using an older version of libc++ (your problem is in the LLVM bugtracker, see below).

The change was introduced in revision 162108:

--- istream     (revision 162607)
+++ istream     (revision 162608)
@@ -1263,6 +1263,7 @@
     try
     {
 #endif  // _LIBCPP_NO_EXCEPTIONS
+        this->clear(this->rdstate() & ~ios_base::eofbit);
         sentry __sen(*this, true);
         if (__sen)
         {

The log concerning the change:

$ svn log -r 162608

------------------------------------------------------------------------ r162608 | hhinnant | 2012-08-25 00:03:03 +0200 (Sat, 25 Aug 2012) | 1 line

Have basic_istream seekg, putback and unget first clear eofbit. Fixes http://llvm.org/bugs/show_bug.cgi?id=13089.

like image 42
us2012 Avatar answered Sep 19 '22 12:09

us2012