Каково поведение метода Cstream ostream :: exceptions (состояние iostate) C ++? - PullRequest
0 голосов
/ 22 февраля 2019

Я нахожусь в процессе написания своей собственной выходной потоковой библиотеки, и я пытаюсь имитировать поведение std :: ostream, где оно не конфликтует с новым поведением, которого я пытаюсь достичь.В настоящее время я пытаюсь имитировать этот интерфейс, унаследованный от ios:

std::ostream::exceptions(ios::iostate state)

Согласно cplusplus.com :

"этот метод устанавливает новое исключениемаска для потока и очищает флаги состояния ошибки потока (как если бы вызывался член clear ()). "

Мне не было ясно, означает ли это, что все флаги будут сброшены или толькоони устанавливаются в маске исключений, поэтому я написал тестовую программу, но получил довольно неожиданные результаты.Вот программа:

#include <sstream>
#include <iostream>

using namespace std;
int main(int argc, char** argv)
{
    ostringstream oss;
    try
    {
        cout << "            badbit           = " << ios::badbit        << "\n";
        cout << "            eofbit           = " << ios::eofbit        << "\n";
        cout << "            failbit          = " << ios::failbit       << "\n\n";

        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n\n";

        cout << "executing:  oss.setstate(ios::badbit | ios::failbit);" << "\n";
        oss.setstate(ios::badbit | ios::failbit);
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n\n";

        cout << "executing:  oss.exceptions(ios::failbit);"             << "\n";
        oss.exceptions(ios::failbit);
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n";
    }
    catch(const exception& x)
    {
        cout << endl;
        cout << "**** EXCEPTION THROWN ****"                            << "\n";
        cout << argv[0] << ":  " << x.what() << endl;
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n";
        return 1;
    }
    catch(...)
    {
        cerr << argv[0] << ":  unknown exception." << endl;
        return 1;
    }
    return 0;
}

А вот и вывод:

matt@dworkin:~/dev/ostream/libs/ostream$ g++ --version
g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

matt@dworkin:~/dev/ostream/libs/ostream$ g++ --std=c++17 foo.cpp
matt@dworkin:~/dev/ostream/libs/ostream$ ./a.out

            badbit           = 1
            eofbit           = 2
            failbit          = 4

            oss.rdstate()    = 0
            oss.exceptions() = 0

executing:  oss.setstate(ios::badbit | ios::failbit);
            oss.rdstate()    = 5
            oss.exceptions() = 0

executing:  oss.exceptions(ios::failbit);

**** EXCEPTION THROWN ****
./a.out:  basic_ios::clear: iostream error
            oss.rdstate()    = 5
            oss.exceptions() = 4

Итак, основываясь на документах cplusplus.com, я не ожидал, что будет выдано исключение.И как видно из вывода, сгенерированного из обработчика исключений, никакие флаги состояния никогда не очищались.Так это ошибка компилятора, ошибка документации или я что-то упустил?

В качестве отступления, я предпочитаю поведение, демонстрируемое, по сравнению с документированным поведением.Мне кажется странным, что запрос об ошибках будет иметь побочный эффект удаления существующих ошибок.На самом деле я сначала реализовал его так же, как, очевидно, делает g ++ (при условии, что так будет работать наверняка), и только потом прочитал документы по этому методу.

1 Ответ

0 голосов
/ 22 февраля 2019

cplusplus.com не так.Они верны, что clear вызывается exceptions, но не вызывается для очистки состояния, а состояние не очищается.

Несмотря на название, clear используется в серверной части iostreams, , включая setstate сам , для выполнения тяжелой работы для множества настроек, а не толькоочистка от состояния потока.Таким образом, это логическое место для размещения исключений и других действий, связанных с флагами.

В exceptions оказывается, clear используется в основном для проверки существующих флагов, чтобы вызвать исключение в случае любогожелаемых флагов уже установлены.Чтобы фактически удалить флаги после исключения, по-прежнему требуется вызов clear для удаления флагов ошибок.

...