Introducción
Un programador de C++ debe lidiar continuamente con múltiples desafíos: garantizar una correcta recuperación de los programas ante excepciones, prevenir
bugs tales como accesos fuera de rango o referencias colgantes, adoptar estrategias ante un posible agotamiento de la memoria y un largo etcétera. En este
post trataremos de arrojar algo de luz sobre cómo manejar tales situaciones de forma correcta. No en vano, una de las características definitorias de cualquier lenguaje de programación es, precisamente, el conjunto de herramientas que pone a nuestra disposición para realizar esta importante labor.
Centraremos nuestra atención, en particular, en las llamadas a funciones. Distinguiremos dos categorías principales de incidencias por las que una función puede no alcanzar sus objetivos: recuperables e irrecuperables. Un lenguaje más reciente, Rust, maneja dichas categorías de forma claramente diferenciada, proporcionando un tipo de retorno
Result<T,E> para errores recuperables (el cual contiene un valor de tipo esperado
T o bien un elemento de error
E) y una macro
panic! para detener la ejecución del proceso en caso de producirse una incidencia irrecuperable [1]. Por defecto, C++ trata la primera categoría mediante el uso de
excepciones, cuya utilidad pondremos en valor en este
post, aunque el empleo de tipos variantes sea sin duda factible gracias a bibliotecas como
Boost.Outcome [2]. Como discutiremos también, el tratamiento de errores irrecuperables debería descansar en el uso de
contratos.