应该使用std :: ws操纵器从流中提取是否会引发失败位?在下面的代码中,Clang编译(在Xcode 4.5.1中)程序会失败最终的断言。 EOF显然s >> std::ws
导致失败。然而,GCC 4.7.2通过了断言。哪个是对的?
#include <iostream>
#include <sstream>
#include <cassert>
int main(int argc, const char * argv[])
{
{
// Read string with trailing ws.
std::istringstream s( "test " );
std::string test;
s >> std::ws;
assert( !s.fail() ); // No ws to skip, but no failure.
s >> test;
assert( test == "test" );
assert( !s.fail() );
s >> std::ws;
assert( !s.fail() ); // No prob skipping trailing ws.
}
{
// Retry with no trailing ws.
std::istringstream s( "test" );
std::string test;
s >> std::ws;
assert( !s.fail() ); // No ws to skip, but no failure.
s >> test;
assert( test == "test" );
assert( !s.fail() );
s >> std::ws;
assert( !s.fail() ); // CLANG: Skipping absent ws at eof raises failbit.
}
return 0;
}
答案 0 :(得分:4)
我相信libc ++正在正确实施标准。
[我引用了N3290,这是C ++ 11标准草案。 C ++ 14不会改变这一点。 ]
[istream.manip]中描述了 ws
,其中声明:
效果:表现为无格式输入功能(如 27.7.2.3,第1段),但不计算数量 提取的字符,不会影响返回的值 随后调用is.gcount()。构建一个岗哨对象后 只要下一个可用字符c是,就会提取字符 空格或直到序列中没有其他字符。 空白字符用相同的标准区分 由sentry :: sentry使用(27.7.2.1.3)。如果ws停止提取字符 因为没有更多可用它设置eofbit,但不是失败位。
确定正确行为的关键词是&#34;在构建岗哨对象后#34;
Sentry对象在[istream :: sentry]中描述,文本开始......
1类sentry定义了一个负责执行异常安全前缀和后缀操作的类。
显性哨兵(basic_istream&amp; is,bool noskipws = false);
2效果:如果is.good()为false,则调用is.setstate(failbit)。否则,准备 格式化或&gt;无格式输入。 ...... 等等 ...
这是唯一可用的哨兵构造函数,因此是libc ++使用的构造函数。
因此在提取任何字符之前设置失败位,因此段落末尾的文本不适用。如果流包含" "
(即末尾的单个空格),则调用std::ws
不会设置失败位,只是eof(这是OP预期会发生的)。
答案 1 :(得分:3)
C ++ 11,§27.7.2.4/ 1:
如果
ws
停止提取字符,因为没有更多可用字符,则设置eofbit
,而不是failbit
。
因此,ws
操纵器未直接设置failbit
。但是,正如Marshall Clow在他的回答中指出的那样,它不需要 - 它需要创建一个岗哨对象,并且如果!stream.good()
,则需要岗哨对象来设置故障位。