2013-02-11 78 views
11

直观地说,从C++规范来看,它在我看来好像istream::putback(c)应该总是安排输入缓冲区,以便下一个调用istream::peek()应该读取字符c。这是不正确的?我问,因为在所有情况下,使用Xcode 4.6的最新版本的libC++ shipping似乎不会强制执行此行为 - 特别是当最后一个字符位于EOF时。如果您使用unget()而不是putback(c),情况也是如此。不应该istream :: peek()总是返回你刚刚putback()?

是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; 
} 
+2

在'putback(c)'之后是否设置了'eofbit','failbit','badbit'? (仅供参考:使用libstdC++ 4.7,其中没有一个设置,流是'good()'。) – us2012 2013-02-11 20:48:08

+0

+1。看起来像在r162608中修复的libC++中的错误。 – 2013-02-11 21:50:44

回答

6

有实际上已经改变到putback功能在C++ 11:

§27.7.2.3/ 34

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

效果:表现为未格式化的输入功能(如27.7.2.3段落中所述),除了该功能首先清除eofbit。 ...

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

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

4

博佩尔森对标准是正确的。您可能正在使用旧版本的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的日志-r 162608

--------- -------------------------------------------------- ------------- r162608 | hinnant | 2012-08-25 00:03:03 +0200(2012年8月25日周六)| 1 line

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

相关问题