Translate

viernes, 19 de diciembre de 2025

std::optional vs std::variant vs std::expected en C++


El C++ moderno (C++17–C++23) nos ofrece varias formas seguras de representar alternativas o ausencia de valor, sin recurrir a punteros nulos o excepciones.

Tres herramientas destacan: std::optional, std::variant y std::expected. Aunque parecidas, resuelven problemas distintos.

std::optional<T> : Presencia o ausencia de un valor. Introducido en C++17, modela un valor que puede o no existir.


std::optional<int> findId(std::string name);


Si la búsqueda tiene éxito → return id;

Si no → return std::nullopt;


Ventajas:

  • Ligero y simple: ideal para “valor o nada”.
  • No necesita excepciones.
  • Soporta monadic ops (transform, and_then en C++23).


Cuándo no usarlo:

  • No distingue causas de error (solo “existe o no”).
  • No reemplaza un tipo con múltiples variantes.


std::variant<Ts...> — Uno de varios tipos posibles


También desde C++17, std::variant es un sum type que puede contener exactamente uno de los tipos listados.


std::variant<int, std::string> value = 10;


Podés inspeccionar su contenido con std::visit:


std::visit([](auto&& v) { std::cout << v; }, value);


Ventajas

  • Representa alternativas tipadas.
  • Útil cuando las opciones no son errores, sino formas distintas de un mismo dato.
  • Type-safe, reemplaza union.


Cuándo no usarlo:

  • No expresa “éxito o fallo” naturalmente.
  • Puede ser más complejo que un optional.


std::expected<T, E> — Resultado o error. Agregado oficialmente en C++23, inspirado en Rust y en la monada Either.


std::expected<int, std::string> parseInt(std::string s);


Si tuvo éxito → return 42;

Si falló → return std::unexpected("error");


Ventajas

  • Modelo explícito de éxito / error sin excepciones.
  • Evita throws y captura el por qué del fallo.
  • Monádico (transform, and_then, etc.).


Cuándo no usarlo

  • Cuando solo importa si hay o no valor (`std::optional` es más simple).
  • Si necesitás representar varias formas de datos no relacionadas (std::variant es mejor).


En resumen, std::optional modela la ausencia, std::variant modela alternativas, y std::expected modela el éxito o el error.

Juntas, son el núcleo de la programación expresiva y segura del C++ moderno.