No sorprenderé a nadie si digo que las macros de C son peligrosas. Ignoran completamente el sistema de tipos e incluso la sintaxis del lenguaje, pues suceden en un paso de preprocesador que se basa en un muy simple analizador léxico y consisten de sustitución textual. Es fácil introducir con ellas errores o ineficiencias sutiles que escapen a la vista pero que puedan explotar inesperadamente en el momento más inoportuno. El problema principal que resolvían en C, el código genérico, está ampliamente resuelto en C++ mediante las templates, que lo hacen además de una forma mucho más segura y expresiva. Sin embargo, sigue habiendo cosas que sólo las macros pueden hacer. Es más, conforme van metiendo más cosas a C++, el poder de las macros aumenta también de maneras a veces insospechadas. Y precisamente por estas cosas que sólo las macros pueden hacer yo creo que todavía hay un lugar para ellas en C++.
Lo primero que hay que decir es que las macros no deberían ser nunca la solución si hay otra herramienta en el lenguaje que lo haga. Las constantes se hacen con
y las funciones genéricas con templates. Esto no se discute. Si alguien sigue haciendo
#define MAX_ARRAY_SIZE 64
en 2020 por favor que se lo haga mirar. Incluso se podría discutir que el código de producción no debería usar macros, o debería usar las mínimas posibles. Un proyecto atado por los ciclos de reproducción ampliada del capital por lo general no puede permitirse riesgos que le puedan explotar en la cara cuando existen alternativas más seguras. De todas formas, no es de esto de lo que vengo a hablar.
El lugar en el que las macros son valiosas es en la investigación. En esos proyectos que tienen como objetivo empujar las barreras de lo que creemos expresable con el lenguaje. En bibliotecas como boost, cuyas bibliotecas experimentales han acabado muchas veces sentando las bases de lo que varios años más tarde sería el estándar. Las macros permitieron en C++98 implementar
, Boost Concept Check o Boost Parameter, que luego se acabarían convirtiendo en el range-for the C++11 o los conceptos de C++20. Los parámetros con nombre todavía no han entrado en el estándar, pero el mero hecho de que algo así sea expresable en C++ ya es como para quitarse el sombrero. En general, las macros permiten implementar nuevas herramientas en el lenguaje, y por lo tanto permiten experimentar y probar qué más podríamos querer añadir al lenguaje, y jugar con ello y ponerlo a prueba. Y sí, puede que a veces se vea un poco raro, o se rompa, o no se pueda hacer todo. Ya hemos dicho antes que no debería usarse en la industria. Pero con un poco de imaginación las macros permiten hacer verdadera magia. Además, lo hacen accesible. No todo el mundo tiene el tiempo ni el conocimiento como para clonar clang y programar sus modificaciones. Las macros permiten extender el lenguaje desde dentro del propio lenguaje y con las herramientas del lenguaje, permitiendo experimentar de esta manera a cualquiera con un poco de paciencia y una tolerancia relativamente alta a los errores de compilador crípticos.
Pocos lenguajes tienen, dentro del propio lenguaje, una herramienta tan poderosa como para extenderlo y hacer nuestras propias herramientas. Puede que sea primitivo y peligroso, y que no debamos usarlo para cosas serias, pero deberíamos agradecer que esté ahí por todo lo que ha hecho por el desarrollo de C++. Durante toda la historia de C++ las macros han permitido y siguen permitiendo a programadores jugar a cómo sería el lenguaje de programación si cambiara tal cosa, y se han dado grandes hallazgos por el camino. Tal vez no sea exagerar decir que hay partes de C++11 y posteriores que tenemos gracias a las macros.