Подтвердить что ты не робот

Как предоставить потокам сообщения о лучших исключениях?

Проблема

Как сейчас, поддержка исключений для потоков ужасна. Когда библиотека Boost.System была принята в С++ 11, у одного создалось впечатление, что, возможно, исключения будут улучшаться. Все изменения были заменены std::exception на std::system_error. Хотя <system_error> является хорошей библиотекой для разработчиков, стандартный комитет и разработчики стандартных библиотек не предприняли никаких шагов по его использованию для улучшения сообщений об исключениях.

Чтобы дать представление о том, как это ужасно, здесь краткое изложение того, что происходит:

  • Произошла ошибка.

  • setstate используется для установки badbit или failbit.

  • clear вызывается setstate.

  • Если исключения включены, clear выдаст ios_base::failure.

Да, это означает, что для ВСЕХ ошибок генерируется одно и то же ненужное сообщение об исключении. Это указано на уровне basic_ios, поэтому все производные классы страдают от этой проблемы. Оскорбительная цитата:

[iostate.flags]/4 Эффекты: Если ((state | (rdbuf() ? goodbit : badbit)) & exceptions()) == 0, возвращается. В противном случае функция бросает объект fail класса basic_ios::failure (27.5.3.1.1), построенные с определенными параметрами аргументов.

Здесь приведен пример того, что "значения аргументов, определяемых реализацией":

ios_base::clear: unspecified iostream_category error

Есть ли легкое исправление?

Ни Boost.Filesystem, ни Boost.Iostreams не являются заменой для <iostream>. Первая представляет собой библиотеку для портативного управления файловой системой (и, вероятно, появится в следующей версии С++), в то время как последняя имеет какое-то отношение к... Источники и стоки. В документации указано, что она делегирует исключения в ios_base::failure в любом случае. Boost.Filesystem предоставляет <boost/filesystem/fstream.hpp>, который использует path вместо аргументов const char* для open(). В нем показан пример того, как можно наследовать стандартные классы библиотек:

  template < class charT, class traits = std::char_traits<charT> >
  class basic_ifstream : public std::basic_ifstream<charT,traits>
  {
  private: // disallow copying
    basic_ifstream(const basic_ifstream&);
    const basic_ifstream& operator=(const basic_ifstream&);

  public:
    basic_ifstream() {}

    // use two signatures, rather than one signature with default second
    // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416)

    explicit basic_ifstream(const path& p)
      : std::basic_ifstream<charT,traits>(p.BOOST_FILESYSTEM_C_STR, std::ios_base::in) {}

    basic_ifstream(const path& p, std::ios_base::openmode mode)
      : std::basic_ifstream<charT,traits>(p.BOOST_FILESYSTEM_C_STR, mode) {}

    void open(const path& p)
      { std::basic_ifstream<charT,traits>::open(p.BOOST_FILESYSTEM_C_STR, std::ios_base::in); }

    void open(const path& p, std::ios_base::openmode mode)
      { std::basic_ifstream<charT,traits>::open(p.BOOST_FILESYSTEM_C_STR, mode); }

    virtual ~basic_ifstream() {}
  };

Это аккуратный трюк, за исключением того, что наша нарушающая функция не виртуальна и все в basic_ios, есть комбинаторный взрыв того, что мы должны переопределить:

диаграмма наследования iostream

Я подозреваю, что требуется полная переписывание, потому что просто заменить clear() будет недостаточно. Поток может завершиться неудачей по нескольким причинам, но есть только один тип исключения. Хотя std::system_error дает нам лучшие инструменты выражения ошибок, это не помогает, если, опять же, нет способа отличить источник ошибки.

Однако я не писатель библиотеки и не хочу заниматься этой задачей. Есть ли другие варианты, кроме перечисленных мной?

4b9b3361

Ответ 1

Boost - это проект с открытым исходным кодом, так что я вижу его в двух вариантах:

  • Пожаловаться. Либо напишите отчет об ошибке, либо получите список рассылки, и предложите расширение или и то, и другое. Если сообщество считает, что у вас есть хороший момент, кто-то может взять его на себя.
  • Сделайте 1, затем сделайте что-нибудь об этом. Вероятно, вы получите некоторую поддержку от сообщества. Возможно, вы не были писателем в библиотеке, но, возможно, люди, поддерживающие повышение, тоже не были, пока они не были.

Нет волшебного способа исправить это, кто-то должен выполнить эту работу.