11

直观地说,从 C++ 规范来看,在我看来,它似乎istream::putback( c )应该总是安排输入缓冲区,以便下一次调用istream::peek()应该读取字符c。这不正确吗?我问是因为 Xcode 4.6 附带的最新版本的 libc++ 似乎并未在所有情况下都强制执行此行为——尤其是当最后一个字符位于 EOF 时。如果您使用unget()而不是putback( c ).

libc++ 的行为是正确的,还是我对如何putback()/unget()工作的直觉正确?

考虑这个示例代码,它适用于 libstdc++ 但不适用于 libc++(断言失败)。

#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;
}
4

2 回答 2

6

实际上putback,C++11 中的函数发生了变化:

§27.7.2.3/34

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

效果:表现为一个未格式化的输入函数(如 27.7.2.3,第 1 段所述),除了函数首先清除eofbit. ...

C ++ 03中不存在句子的后半部分。

因此,这可能取决于编译器是否已完全实现此更改,或者您是否使用了所需的选项(-std=C++11?)。

于 2013-02-11T21:03:24.727 回答
4

Bo Persson 关于标准是正确的。您可能使用的是旧版本的 libc++(您的问题出在 LLVM 错误跟踪器中,见下文)。

修订版 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)
         {

有关更改的日志:

$ svn log -r 162608

-------------------------------------------------- ---------------------- r162608 | 希南特 | 2012-08-25 00:03:03 +0200(2012 年 8 月 25 日星期六)| 1 行

有 basic_istream seekg、putback 和 unget 首先清除 eofbit。修复 http://llvm.org/bugs/show_bug.cgi?id=13089

于 2013-02-11T19:41:34.247 回答