Должен ли std :: ws поднять failbit в конце файла?

Должно ли извлечение из потока с помощью манипулятора 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;
}

9

Решение

C ++ 11, §27.7.2.4 / 1:

Если ws перестает извлекать символы, потому что больше нет доступных наборов eofbit, но нет failbit,

Итак ws манипулятор не устанавливается failbit непосредственно. Тем не менее, как отмечает Маршалл Клоу в своем ответе, это не обязательно — требуется создать часовой объект, а часовой объект должен установить битовый бит, если !stream.good(),

3

Другие решения

Я считаю, что 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).

4

По вопросам рекламы [email protected]