Что такое exception_ptr в C++?

«Что такое exception_ptr в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

std::exception_ptr — это тип из заголовка <exception>, представляющий обёртку с разделяемым владением (shared ownership) для захваченного исключения. Он позволяет сохранять и передавать исключения между контекстами, например, между потоками, для отложенной обработки.

Основное применение:

  • Передача исключений из рабочего потока в главный (например, при использовании std::async).
  • Создание цепочек или графов исключений.
  • Реализация механизмов отложенного проброса.

Ключевые функции:

  • std::current_exception() — захватывает текущее активное исключение и возвращает exception_ptr на него. Если исключения нет, возвращает пустой exception_ptr.
  • std::rethrow_exception(exception_ptr p) — пробрасывает копию исключения, на которое указывает p.
  • std::make_exception_ptr(E e) — создаёт exception_ptr на копию исключения e.

Пример передачи исключения между потоками:

#include <iostream>
#include <thread>
#include <exception>
#include <stdexcept>

void worker(std::exception_ptr& eptr) {
    try {
        // Имитация работы, которая может завершиться ошибкой
        throw std::runtime_error("Ошибка в рабочем потоке");
    } catch (...) {
        eptr = std::current_exception(); // Захватываем исключение для передачи
    }
}

int main() {
    std::exception_ptr eptr;
    std::thread t(worker, std::ref(eptr));
    t.join();

    // Обработка исключения из потока в главном потоке
    if (eptr) {
        try {
            std::rethrow_exception(eptr);
        } catch (const std::exception& e) {
            std::cout << "Поймано исключение из потока: " << e.what() << 'n';
        }
    }
    return 0;
}

Важно: exception_ptr безопасен для копирования и присваивания; ресурсы освобождаются автоматически, когда на исключение не остаётся ссылок.