std :: ws поведение в EOF - PullRequest
       38

std :: ws поведение в EOF

3 голосов
/ 07 августа 2020

Я обнаружил разницу в поведении разных компиляторов. Предположим, что следующий код:

#include <sstream>
#include <iostream>

using namespace std;

int main() {
    istringstream ss("100");
    int val;
    ss >> val;
    cout << "fail: " << ss.fail() << " eof: " << ss.eof() << endl;
    ss >> std::ws;
    cout << "fail: " << ss.fail() << " eof: " << ss.eof() << endl;
}

Результат, сгенерированный VS2019 и Clang 10 с libc ++:

fail: 0 eof: 1
fail: 1 eof: 1

В то время как VS2015 и G CC 10.2 с libstdc ++ генерирует:

fail: 0 eof: 1
fail: 0 eof: 1

Итак, вопрос в том, какая реализация правильная? Следует ли std::ws устанавливать failbit, когда eofbit уже установлен?

Я поискал std::ws в стандарте, в котором говорится:

30.7.4.4 Стандартные манипуляторы basic_istream [istream .manip]

шаблон basic_istream & ws (basic_istream & is);

Эффекты: Ведет себя как неформатированная функция ввода (30.7.4.3), за исключением того, что не подсчитывает количество извлеченных символов и не влияет на значение, возвращаемое последующими вызовами is.gcount ( ). После создания сторожевой объект извлекает символы до тех пор, пока следующий доступный символ c является пробелом или пока в последовательности не останется символов. Пробельные символы различаются по тому же критерию, что и sentry :: sentry (30.7.4.1.3). Если ws перестает извлекать символы, потому что их больше нет, он устанавливает eofbit, но не failbit.

Итак, в конце явно указано, что он устанавливает eofbit, но не failbit, когда символы недоступны. Но тогда он также ведет себя как неформатированная функция ввода, которая создает объект sentry. Конструктор sentry затем вызовет is.setstate(failbit), если is.good() ложно. Так что в каком-то смысле обе реализации не совсем ошибочны. Может ли кто-нибудь, кто лучше разбирается в стандартном языке, пояснить, какой вариант правилен и где мне следует сообщить об ошибке?

1 Ответ

0 голосов
/ 07 августа 2020

failbit должно быть установлено. Это делается с помощью объекта sentry, который ws конструирует первым делом.

[istream :: sentry] / 2 explicit sentry(basic_istream<charT, traits>& is, bool noskipws = false); Эффекты: Если is.good() равно false, вызывает is.setstate(failbit). В противном случае ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...