std::current_exception în C++

Salvează excepția prinsă într-un exception_ptr, ca să fie aruncată din nou mai târziu, chiar pe alt fir.

Sintaxă
#include <exception>
std::exception_ptr current_exception() noexcept;
[[noreturn]] void rethrow_exception(std::exception_ptr p);

Ce face std::current_exception

În interiorul unui bloc catch, std::current_exception() returnează un std::exception_ptr către excepția tratată acum. Obiectul poate fi păstrat, copiat și trimis altui fir de execuție.

std::rethrow_exception(p) aruncă din nou excepția salvată, cu tipul ei original, deci poate fi prinsă normal cu catch. Așa transmite std::future excepțiile de pe firul de lucru către cel care apelează get().

Un exception_ptr gol (implicit) este egal cu nullptr, deci poți verifica simplu dacă a apărut o eroare.

Ce returnează

current_exception returnează un std::exception_ptr (gol dacă nu se tratează nicio excepție). rethrow_exception nu returnează.

Exemple

Exemplul 1: Eroare de pe un fir de execuție, tratată în main

#include <exception>
#include <print>
#include <stdexcept>
#include <thread>

int main() {
    std::exception_ptr eroare;

    std::thread t([&eroare] {
        try {
            throw std::runtime_error("conexiunea la baza de date a eșuat");
        } catch (...) {
            eroare = std::current_exception();
        }
    });
    t.join();

    if (eroare) {
        try {
            std::rethrow_exception(eroare);
        } catch (const std::exception& e) {
            std::println("Eroare de pe fir: {}", e.what());
        }
    }
}

Rezultat

Eroare de pe fir: conexiunea la baza de date a eșuat

Exemplul 2: Colectarea erorilor și raportarea la final

#include <exception>
#include <print>
#include <stdexcept>
#include <string>
#include <vector>

void proceseaza(const std::string& fisier) {
    if (fisier.ends_with(".exe")) throw std::invalid_argument(fisier + ": tip nepermis");
    if (fisier.empty()) throw std::runtime_error("nume gol");
}

int main() {
    std::vector<std::exception_ptr> erori;
    for (std::string f : {"poza.jpg", "virus.exe", "", "nota.txt"}) {
        try {
            proceseaza(f);
        } catch (...) {
            erori.push_back(std::current_exception());
        }
    }

    std::println("{} erori:", erori.size());
    for (const auto& e : erori) {
        try { std::rethrow_exception(e); }
        catch (const std::exception& ex) { std::println("- {}", ex.what()); }
    }
}

Rezultat

2 erori:
- virus.exe: tip nepermis
- nume gol

Greșeli frecvente

  • Apelezi std::rethrow_exception cu un exception_ptr gol. Comportamentul este nedefinit; verifică întâi if (p).

Comenzi înrudite

  • std::promise: Capătul de scriere al unui std::future: un fir promite o valoare și o trimite cu set_value.
  • std::future: Un rezultat care va fi disponibil în viitor (de la std::async sau std::promise); get() îl așteaptă și îl returnează.
  • std::exception: Clasa de bază a tuturor excepțiilor din biblioteca standard; what() returnează mesajul erorii.
  • std::terminate: Oprește imediat programul; este apelată automat când o excepție nu este prinsă nicăieri.
  • try, catch: try marchează codul care poate arunca o excepție, iar blocurile catch prind și tratează excepțiile de un anumit tip.