Esto comenzó como una pregunta SO, pero me di cuenta de que es bastante poco convencional y, según la descripción real de los sitios web, podría ser más adecuado para los programadores, ya que la pregunta tiene mucho peso conceptual.
He estado aprendiendo LibTooling clang y es una herramienta muy poderosa capaz de exponer todo el "meollo de la cuestión" del código de una manera amigable, es decir, de una manera semántica , y no adivinando tampoco. Si clang puede compilar su código, entonces clang está seguro de la semántica de cada personaje dentro de ese código.
Ahora permíteme dar un paso atrás por un momento.
Hay muchos problemas prácticos que surgen cuando uno participa en la metaprogramación de plantillas C ++ (y especialmente cuando se aventura más allá de las plantillas en el territorio de las macros inteligentes, aunque aterradoras). Para ser honesto, para muchos programadores, incluido yo mismo, muchos de los usos comunes de las plantillas también son algo terroríficos.
Supongo que un buen ejemplo sería cadenas de tiempo de compilación . Esta es una pregunta que tiene más de un año, pero está claro que C ++ en este momento no facilita esto a los simples mortales. Si bien mirar estas opciones no es suficiente para provocarme náuseas, sin embargo, no me deja seguro de poder producir un código de máquina mágico y de máxima eficiencia para adaptarse a cualquier aplicación elegante que tenga para mi software.
Quiero decir, seamos sinceros, amigos, las cadenas son bastante simples y básicas. Algunos de nosotros solo queremos una manera conveniente de emitir código de máquina que tenga ciertas cadenas "cocidas" significativamente más de lo que obtenemos al codificarlo de manera directa. En nuestro código C ++.
Ingrese clang y LibTooling, que expone el árbol de sintaxis abstracta (AST) del código fuente y permite que una aplicación C ++ personalizada simple manipule de manera correcta y confiable el código fuente sin procesar (usando Rewriter
) junto con un rico modelo semántico orientado a objetos de todo en el AST. Maneja muchas cosas. Conoce las macro expansiones y te permite seguir esas cadenas. Sí, estoy hablando de la transformación o traducción del código fuente a fuente.
Mi tesis fundamental aquí es que el sonido metálico ahora nos permite crear ejecutables que pueden funcionar como las etapas de preprocesador personalizadas ideales para nuestro software C ++, y podemos implementar estas etapas de metaprogramación con C ++. Simplemente estamos limitados por el hecho de que esta etapa debe tomar la entrada que es un código C ++ válido y producir como salida un código C ++ más válido. Además de cualquier otra restricción que aplique su sistema de compilación.
La entrada debe estar al menos muy cerca de un código C ++ válido porque, después de todo, clang es el front-end del compilador y solo estamos hurgando y siendo creativos con su API. No sé si hay alguna disposición para poder definir una nueva sintaxis para usar, pero claramente tenemos que desarrollar las formas de analizarla correctamente y agregarla al proyecto clang para poder hacer esto. Esperar más es tener algo en el proyecto clang que está fuera de alcance.
No es un problema. Me imagino que algunas funciones macro no-op pueden manejar esta tarea.
Otra forma de ver lo que estoy describiendo es implementar construcciones de metaprogramación usando C ++ en tiempo de ejecución manipulando el AST de nuestro código fuente (gracias a clang y su API) en lugar de implementarlas usando las herramientas más limitadas disponibles en el lenguaje mismo. Esto también tiene claros beneficios en el rendimiento de la compilación (los encabezados con plantillas pesadas ralentizan la compilación proporcionalmente a la frecuencia con la que los usas. Muchas cosas compiladas son cuidadosamente emparejadas y desechadas por el enlazador).
Sin embargo, esto tiene el costo de introducir uno o dos pasos adicionales en el proceso de compilación y también el requisito de escribir un software (ciertamente) algo más detallado (pero al menos es un tiempo de ejecución C ++ sencillo) como parte de nuestra herramienta .
Esa no es la imagen completa. Estoy bastante seguro de que existe un espacio mucho más amplio de funcionalidad que se puede obtener generando código que es extremadamente difícil o imposible con las características principales del lenguaje. En C ++ puede escribir una plantilla o una macro o una combinación loca de ambos, pero en una herramienta de sonido puede modificar clases y funciones de CUALQUIER manera que pueda lograr con C ++, en tiempo de ejecución , mientras tiene acceso completo al contenido semántico, Además de plantilla y macros y todo lo demás.
Entonces, me pregunto por qué todos ya no están haciendo esto. ¿Es que esta funcionalidad de clang es tan nueva y nadie está familiarizado con la enorme jerarquía de clases de AST de clang? Eso no puede ser.
Quizás solo estoy subestimando la dificultad de esto un poco, pero hacer "manipulación de cadenas en tiempo de compilación" con una herramienta de sonido metálico es casi criminalmente simple. Es detallado, pero es increíblemente sencillo. Todo lo que se necesita es un montón de funciones macro no operativas que se correlacionen con std::string
operaciones reales reales . El complemento clang implementa esto mediante la obtención de todas las llamadas macro no-op relevantes, y realiza las operaciones con cadenas. Esta herramienta luego se inserta como parte del proceso de construcción. Durante la compilación, estas llamadas a funciones de macro no operativas se evalúan automáticamente en sus resultados y luego se vuelven a insertar como cadenas de tiempo de compilación simples en el programa. El programa se puede compilar como de costumbre. De hecho, este programa resultante también es mucho más portátil, ya que no requiere un nuevo compilador elegante que admita C ++ 11.