Должно ли извлечение из потока с помощью манипулятора std :: ws когда-либо поднимать бит сбоя? В следующем коде программа, скомпилированная Clang (в Xcode 4.5.1), проваливает окончательное утверждение. очевидно s >> std::ws
на EOF вызывает сбой. И все же 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;
}
C ++ 11, §27.7.2.4 / 1:
Если
ws
перестает извлекать символы, потому что больше нет доступных наборовeofbit
, но нетfailbit
,
Итак ws
манипулятор не устанавливается failbit
непосредственно. Тем не менее, как отмечает Маршалл Клоу в своем ответе, это не обязательно — требуется создать часовой объект, а часовой объект должен установить битовый бит, если !stream.good()
,
Я считаю, что libc ++ реализует стандарт правильно.
[Я цитирую N3290, который является проектом стандарта C ++ 11. C ++ 14 не меняет этого. ]ws
описано в [istream.manip], в котором говорится:
Эффекты: ведет себя как неотформатированная функция ввода (как описано в
27.7.2.3, пункт 1), за исключением того, что он не учитывает количество
извлеченные символы и не влияет на значение, возвращаемое
последующие вызовы is.gcount (). После постройки сторожевого объекта
извлекает символы, пока следующий доступный символ c
пробел или до тех пор, пока в последовательности не останется больше символов.
Пробельные символы различаются по тому же критерию, что и
используется sentry :: sentry (27.7.2.1.3). Если ws перестает извлекать символы
потому что больше нет доступных он устанавливает eofbit, но не бит сбоя.
Ключевая фраза здесь для определения правильного поведения — «после построения сторожевого объекта».
Sentry объекты описаны в [istream :: sentry], и там начинается текст …
1 Класс sentry определяет класс, который отвечает за выполнение операций префикса и суффикса исключительной ситуации.
явный часовой (basic_istream& is, bool noskipws = false);
2 Эффекты: если is.good () имеет значение false, вызывает is.setstate (failbit). В противном случае готовится к
отформатированный или> неформатированный ввод. …и так далее…
Это единственный доступный конструктор часового типа, так что это тот, который использует libc ++.
Таким образом, бит сбоя устанавливается перед извлечением любых символов, поэтому текст в конце абзаца не применяется. если поток содержал " "
(то есть один пробел в конце), затем вызывая std::ws
не устанавливает бит сбоя, просто eof (что и должно ожидать OP).