21 Language support library [language.support]

21.8 Exception handling [support.exception]

Заголовок <exception> определяет несколько типов и функций, связанных с обработкой исключений в программе C ++.

21.8.1 Header <exception> synopsis [exception.syn]

namespace std {
  class exception;
  class bad_exception;
  class nested_exception;

  using terminate_handler = void (*)();
  terminate_handler get_terminate() noexcept;
  terminate_handler set_terminate(terminate_handler f) noexcept;
  [[noreturn]] void terminate() noexcept;

  int uncaught_exceptions() noexcept;

  using exception_ptr = unspecified;

  exception_ptr current_exception() noexcept;
  [[noreturn]] void rethrow_exception(exception_ptr p);
  template<class E> exception_ptr make_exception_ptr(E e) noexcept;

  template <class T> [[noreturn]] void throw_with_nested(T&& t);
  template <class E> void rethrow_if_nested(const E& e);
}

Смотрите также:[except.special].

21.8.2 Class exception [exception]

namespace std {
  class exception {
  public:
    exception() noexcept;
    exception(const exception&) noexcept;
    exception& operator=(const exception&) noexcept;
    virtual ~exception();
    virtual const char* what() const noexcept;
  };
}

Класс exception определяет базовый класс для типов объектов, создаваемых в качестве исключений компонентами стандартной библиотеки C ++, и определенных выражений для сообщения об ошибках, обнаруженных во время выполнения программы.

Каждый класс стандартной библиотекиT , производный от класса,exception должен иметь общедоступный конструктор копии и общедоступный оператор присваивания копии, которые не завершаются с исключением. Эти функции-члены должны соответствовать следующему постусловию: если два объектаlhs иrhs оба имеют динамический типT иlhs являются копиейrhs, то strcmp(lhs.what(), rhs.what()) должны быть равны 0.

exception() noexcept;

Effects: Создает объект класса exception.

exception(const exception& rhs) noexcept; exception& operator=(const exception& rhs) noexcept;

Effects: Копирует exception объект.

Postconditions: Если*this иrhs оба имеют динамический тип,exception значение выраженияstrcmp(what(), rhs.what()) должно быть равно 0.

virtual ~exception();

Effects: Уничтожает объект класса exception.

virtual const char* what() const noexcept;

Returns: An реализации определенных НТБ .

Remarks: Сообщение может быть null-terminated multibyte string, подходящим для преобразования и отображенным как wstring ([string.classes],[locale.codecvt]). Возвращаемое значение остается действительным до тех пор, пока объект исключения, из которого оно получено, не будет уничтожен или неconst будет вызвана функция, не являющаяся членом объекта исключения.

21.8.3 Class bad_­exception [bad.exception]

namespace std {
  class bad_exception : public exception {
  public:
    bad_exception() noexcept;
    bad_exception(const bad_exception&) noexcept;
    bad_exception& operator=(const bad_exception&) noexcept;
    const char* what() const noexcept override;
  };
}

Класс bad_­exception определяет тип объекта, на который ссылаетсяexception_­ptr возвращаемый из вызоваcurrent_­exception ([propagation]), когда текущий активный объект исключения не удается скопировать.

bad_exception() noexcept;

Effects: Создает объект класса bad_­exception.

bad_exception(const bad_exception&) noexcept; bad_exception& operator=(const bad_exception&) noexcept;

Effects: Копирует объект класса bad_­exception.

const char* what() const noexcept override;

Returns: An реализации определенных НТБ .

Remarks: Сообщение может быть null-terminated multibyte string, подходящим для преобразования и отображенным как wstring ([string.classes],[locale.codecvt]).

21.8.4 Abnormal termination [exception.terminate]

21.8.4.1 Type terminate_­handler [terminate.handler]

using terminate_handler = void (*)();

Тип объекта handler function , вызываемого при завершении обработки исключения.std​::​terminate()

Required behavior: Aterminate_­handler должен прекратить выполнение программы, не возвращаясь к вызывающей стороне.

Default behavior: terminate_­handler Вызовы реализации по умолчаниюabort().

21.8.4.2 set_­terminate [set.terminate]

terminate_handler set_terminate(terminate_handler f) noexcept;

Effects: Устанавливает функцию, обозначеннуюf как текущая функция-обработчик для завершения обработки исключения.

Remarks: Не указано, обозначает ли значение нулевого указателя значение по умолчанию terminate_­handler.

Returns: Предыдущийterminate_­handler.

21.8.4.3 get_­terminate [get.terminate]

terminate_handler get_terminate() noexcept;

Returns: Текущийterminate_­handler. [ Note: Это может быть значение нулевого указателя. ] end note

21.8.4.4 terminate [terminate]

[[noreturn]] void terminate() noexcept;

Remarks: Вызывается реализацией, когда от обработки исключений необходимо отказаться по любой из нескольких причин ([except.terminate]). Также может вызываться непосредственно программой.

Effects: Вызываетterminate_­handler функцию. Не указано, какая terminate_­handler функция будет вызываться, если во время вызова активно исключениеset_­terminate. В противном случае вызывает текущуюterminate_­handler функцию. [ Note: Вterminate_­handler этом контексте значение по умолчанию всегда считается вызываемым обработчиком. ] end note

21.8.5 uncaught_­exceptions [uncaught.exceptions]

int uncaught_exceptions() noexcept;

Returns: Количествоuncaught exceptions.

Remarks: Когдаuncaught_­exceptions() > 0выброс исключения может привести к вызову std​::​terminate().

21.8.6 Exception propagation [propagation]

using exception_ptr = unspecified;

Типexception_­ptr может использоваться для ссылки на объект исключения.

exception_­ptr должны удовлетворять требованиям NullablePointer.

Два ненулевых значения типаexception_­ptr эквивалентны и сравниваются как равные тогда и только тогда, когда они относятся к одному и тому же исключению.

Конструктор по умолчаниюexception_­ptr создает нулевое значение типа.

exception_­ptr не должен быть неявно преобразован в какой-либо арифметический, перечисляемый или указательный тип.

[ Note: Реализация может использовать интеллектуальный указатель с подсчетом ссылок какexception_­ptr. ]end note

В целях определения наличия гонки данных операции с exception_­ptr объектами должны обращаться и изменять только exception_­ptr сами объекты, а не исключения, на которые они ссылаются. Использованиеrethrow_­exception наexception_­ptr объектах, которые ссылаются на один и тот же объект исключения, не должно приводить к гонке за данные. [ Note: Если rethrow_­exception повторно генерируется тот же объект исключения (а не копия), одновременный доступ к этому повторно генерированному объекту исключения может привести к гонке данных. Изменения количестваexception_­ptr объектов, которые ссылаются на конкретное исключение, не приводят к гонке за данные. ] end note

exception_ptr current_exception() noexcept;

Returns: exception_­ptr Объект , который ссылается на currently handled exception или копию текущего перекачиваемого исключения, или нулевойexception_­ptr объект , если исключение не обрабатывается. Указанный объект должен оставаться действительным, по крайней мере, пока существует exception_­ptr объект, который на него ссылается. Если функции необходимо выделить память и попытка не удалась, она возвращает exception_­ptr объект, который ссылается на экземплярbad_­alloc. Не указано, относятся ли возвращаемые значения двух последовательных вызовов к current_­exception одному и тому же объекту исключения. [ Note: То есть не указано,current_­exception создается ли новая копия каждый раз при ее вызове. ] Если попытка скопировать текущий объект исключения вызывает исключение, функция возвращает объект, который ссылается на сгенерированное исключение или, если это невозможно, на экземпляр . [ Конструктор копирования вызванного исключения также может дать сбой, поэтому реализации разрешено заменять объект, чтобы избежать бесконечной рекурсии. ] end noteexception_­ptr bad_­exceptionNote: bad_­exception end note

[[noreturn]] void rethrow_exception(exception_ptr p);

Requires:p не должен быть нулевым указателем.

Throws: Объект исключения, на которыйp ссылается.

template<class E> exception_ptr make_exception_ptr(E e) noexcept;

Effects: Создаетexception_­ptr объект, который ссылается на копиюe, как если бы:

try {
  throw e;
} catch(...) {
  return current_exception();
}

[ Note: Эта функция предназначена для удобства и эффективности. ] end note

21.8.7 nested_­exception [except.nested]

namespace std {
  class nested_exception {
  public:
    nested_exception() noexcept;
    nested_exception(const nested_exception&) noexcept = default;
    nested_exception& operator=(const nested_exception&) noexcept = default;
    virtual ~nested_exception() = default;

    // access functions
    [[noreturn]] void rethrow_nested() const;
    exception_ptr nested_ptr() const noexcept;
  };

  template<class T> [[noreturn]] void throw_with_nested(T&& t);
  template <class E> void rethrow_if_nested(const E& e);
}

Классnested_­exception предназначен для использования в качестве миксина посредством множественного наследования. Он фиксирует текущее обрабатываемое исключение и сохраняет его для дальнейшего использования.

[ Note:nested_­exception имеет виртуальный деструктор, чтобы сделать его полиморфным классом. Его наличие можно проверить с помощьюdynamic_­cast. ]end note

nested_exception() noexcept;

Effects: Конструктор вызываетcurrent_­exception() и сохраняет возвращаемое значение.

[[noreturn]] void rethrow_nested() const;

Effects: Еслиnested_­ptr() возвращает нулевой указатель, функция вызываетstd​::​terminate(). В противном случае он генерирует сохраненное исключение, захваченное*this.

exception_ptr nested_ptr() const noexcept;

Returns: Сохраненное исключение, захваченное этимnested_­exception объектом.

template <class T> [[noreturn]] void throw_with_nested(T&& t);

ПустьU будетdecay_­t<T>.

Requires:U будетCopyConstructible.

Throws: Еслиis_­class_­v<U> && !is_­final_­v<U> && !is_­base_­of_­v<nested_­exception, U> этоtrue, исключение неопределенного типа , который публично производный от обоего U иnested_­exception и построенногоstd​::​forward<T>(t), в противном случае std​::​forward<T>(t).

template <class E> void rethrow_if_nested(const E& e);

Effects: ЕслиE это не полиморфный тип класса, или еслиnested_­exception это недоступный или неоднозначный базовый классE, эффекта не будет. В противном случае выполняет:

if (auto p = dynamic_cast<const nested_exception*>(addressof(e)))
  p->rethrow_nested();