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

Есть ли хорошие описания:: std:: nested_exception и друзей?

Я заметил, что в С++ 11 есть еще несколько интересных объявлений в <exception>. Может ли кто-нибудь проливать свет на то, что они имеют в виду и как их использовать?

Те, о которых мне интересно, следующие:

  • ::std::nested_exception
  • ::std::throw_with_nested
  • ::std::rethrow_if_nested

Кроме того, хотя они кажутся понятными, возможно, было бы хорошо знать, как они работали:

  • ::std::exception_ptr
  • ::std::make_exception_ptr
  • ::std::current_exception
  • ::std::rethrow_exception
4b9b3361

Ответ 1

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

archive::archive(const char* filename)
{
    ifstream file(filename)
    file.exceptions(ios_base::badbit);
    open_archive(file); // throws ios_base::failure, or some other low-level exception.
}

Информация, доступная архиву, не записывается (например, имя файла). Кроме того, вы хотели бы отличить исключения, полученные из класса архива из других исключений.

archive::archive(const char* filename)
{
    try {
        ifstream file(filename)
        file.exceptions(ios_base::badbit);
        open_archive(file); // throws ios_base::failure, or some other low-level exception.
    } catch(const std::exception& e) {
        throw archive_exception("Can't open archive", filename, e.what());
    }
}

Теперь мы добавили семантическую информацию более высокого уровня, которую знает класс archive, но мы также потеряли информацию об исходной причине проблемы (тип e). nested_exception предназначен для решения этой проблемы:

archive::archive(const char* filename)
{
    try {
        ifstream file(filename)
        file.exceptions(ios_base::badbit);
        open_archive(file); // throws ios_base::failure, or some other low-level exception.
    } catch(...) {
        throw_with_nested(archive_exception("Can't open archive", filename));
    }
}

Вся доступная информация записывается. Теперь мы можем в целом получить его на сайте catch:

void print_exception_info(const std::exception& e)
{
    cerr << e.what() << "\n";
    try {
        rethrow_if_nested(e);
    } catch(const std::exception& ne) {
        print_exception_info(ne);
    } catch(...) { }
}

int main() {
    try {
        run();
    } catch(const std::exception& e) {
        print_exception_info(e);
    }
}

Выход будет более описательным, чем раньше. Он будет описывать проблему, начиная с уровня высокого уровня и низкого уровня:

Невозможно открыть архив "my_archive.bin"

Доступ запрещен.

Или, возможно:

Невозможно открыть архив "my_archive.bin"

Запись 'aabb' не найдена.

Функции, работающие с exception_ptr, предназначены для передачи исключений между потоками или, как правило, для хранения исключения для последующего использования. Как они работают, зависит от реализации. Предполагалось, что exception_ptr будет общим указателем на объект исключения. Однако, когда этот указатель создается, при метании исключения или при попытке получить exception_ptr к нему, подлежит реализации. Реализация по-прежнему бесплатна для копирования исключения, когда вы вызываете current_exception().