Ce face std::expected
std::expected<T, E> este ca un std::optional care, în loc de „nimic”, spune de ce lipsește valoarea. Funcția returnează fie valoarea, fie std::unexpected(eroare).
Apelantul verifică cu if (r) sau r.has_value(), apoi citește *r sau r.value(); eroarea se citește cu r.error(). Există și value_or, and_then, transform, ca la optional.
Este o alternativă la excepții pentru erorile previzibile (date invalide, fișier lipsă), în care vrei ca apelantul să fie obligat să trateze eșecul.
Ce returnează
Un obiect care conține fie un T, fie un E. std::unexpected(e) construiește partea de eroare.
Exemple
Exemplul 1: Împărțire cu mesaj de eroare
#include <expected>
#include <print>
#include <string>
std::expected<double, std::string> imparte(double a, double b) {
if (b == 0) {
return std::unexpected("împărțire la zero");
}
return a / b;
}
int main() {
for (double b : {4.0, 0.0}) {
auto r = imparte(10, b);
if (r) {
std::println("10 / {} = {}", b, *r);
} else {
std::println("Eroare: {}", r.error());
}
}
}
Rezultat
10 / 4 = 2.5
Eroare: împărțire la zero
Exemplul 2: Coduri de eroare cu enum
#include <expected>
#include <print>
#include <string>
enum class EroareCont { SoldInsuficient, ContBlocat };
std::expected<int, EroareCont> retrage(int sold, int suma, bool blocat) {
if (blocat) return std::unexpected(EroareCont::ContBlocat);
if (suma > sold) return std::unexpected(EroareCont::SoldInsuficient);
return sold - suma;
}
std::string text(EroareCont e) {
return e == EroareCont::ContBlocat ? "cont blocat" : "sold insuficient";
}
int main() {
auto a = retrage(500, 200, false);
auto b = retrage(500, 900, false);
auto c = retrage(500, 100, true);
std::println("a: sold rămas {}", a.value());
std::println("b: {}", text(b.error()));
std::println("c: {}", c.has_value() ? "ok" : text(c.error()));
std::println("b sau 0: {}", b.value_or(0));
}
Rezultat
a: sold rămas 300
b: sold insuficient
c: cont blocat
b sau 0: 0
Greșeli frecvente
- Apelezi
r.error()cândrconține o valoare (sau*rcând conține eroare). Este comportament nedefinit; verifică întâi cuif (r). - Returnezi eroarea direct (
return "mesaj";) fărăstd::unexpected. Compilatorul încearcă să o transforme în valoareaT; uneori nici nu dă eroare, ci produce un rezultat greșit.
Comenzi înrudite
std::optional: O valoare care poate lipsi: conține fie un obiect de tip T, fie nimic (std::nullopt).std::optional::and_then: Înlănțuiește operații pe un optional: and_then și transform rulează funcția doar dacă există valoare.std::variant: O valoare care are, la un moment dat, exact unul dintre mai multe tipuri posibile (union sigur).try, catch: try marchează codul care poate arunca o excepție, iar blocurile catch prind și tratează excepțiile de un anumit tip.