Gestiunea Monadică a Erorilor fără Excepții cu std::expected în C++23 în C++

Ghid avansat pentru std::expected în C++23: tratarea funcțională a erorilor de sistem fără a plăti costul de performanță al excepțiilor C++, metode monadice (and_then, or_else, transform) și interfețe sigure.

Sintaxă
#include <expected> | std::expected<T, E> f(); | if (!res) { auto err = res.error(); }

În dezvoltarea de software de înaltă performanță (motoare de jocuri, sisteme embedded, microservicii HFT), utilizarea excepțiilor clasice (throw / catch) este adesea descurajată sau complet dezactivată (-fno-exceptions) din cauza costului de performanță la derularea stivei (stack unwinding). Introdus în C++23, tipul de date std::expected<T, E> oferă o alternativă funcțională elegantă: o funcție returnează fie o valoare așteptată de tipul T, fie o eroare detaliată de tipul E (ambele stocate pe stivă fără nicio alocare dinamică).

Tratarea funcțională a erorilor cu std::expected
#include <expected>
#include <string>
#include <print>

enum class EroareFisier {
    Negasit,
    AccesInterzis,
    FormatInvalid
};

// Funcție care returnează fie conținutul fișierului (string), fie un cod de eroare:
std::expected<std::string, EroareFisier> citesteConfig(const std::string& cale) {
    if (cale.empty()) {
        return std::unexpected(EroareFisier::Negasit);
    }
    if (cale == "/etc/shadow") {
        return std::unexpected(EroareFisier::AccesInterzis);
    }
    return "host=127.0.0.1;port=5432;";
}

int main() {
    auto rez = citesteConfig("/etc/shadow");

    if (rez.has_value()) {
        std::println("Configuratie citita: {}", rez.value());
    } else {
        std::println("Eroare intampinata: codul {}", static_cast<int>(rez.error()));
    }

    // Înlănțuire monadică modernă (Monadic Operations):
    auto lungime = citesteConfig("app.conf")
        .transform([](const std::string& s) { return s.length(); })
        .value_or(0);

    std::println("Lungime configuratie valida: {}", lungime);
    return 0;
}