2010-01-28 12 views
5

Creo que la meta programación es muy buena. En particular, me encantan las macros de lisp.Alternativas a las plantillas C++?

Sin embargo, creo que C++ plantilla de chupar porque: 1.
que ralentizan el tiempo de compilación (incluso con encabezados precompilados que terminan siendo 50MB grande si se incluye cualquiera de las cosas que STL).
2. dan terribles errores de compilación/sintaxis que son contradictorios
3. no se diseñaron para la meta programación complicada en primer lugar (generación de errores de compller para números primos/mostrar plantillas son turing completa fue un gran problema en El dia).

Habiendo dicho todo eso, ¿existe una alternativa decente para la metaprogramación de C++? algo así como

* .m -> meta compilador -> * .cpp -> g ++ -> ejecutable?

EDIT:

estoy thikning lo largo de las líneas de "código personalizado generaciones guiones." Me pregunto si hay un conjunto realmente bueno de ellos.

+1

¿Qué tipo de cosas está tratando de generar o calcular? Estructuras? Funciones de línea recta? ¿Código de espagueti? Máquinas de estado? – Potatoswatter

Respuesta

1

Si está usando C++, creo que sus únicas alternativas viables son preprocessor macros, o code-generation personalizado.

El flujo de trabajo que describió básicamente equivaldría a alguna forma de generación de código donde preprocesaría su archivo .m en código compilable de C++. SWIG es un muy buen ejemplo de un proyecto que hace esto.

Personalmente, he tenido un gran éxito escribiendo codificadores en Python, pero creo que cualquier lenguaje de scripting sería igual de bueno. Un paquete que podría ser útil es cog desde nuestro propio Ned Batchelder :)

7

No estoy seguro de que esto sea lo que debería querer, he usado generadores de código para producir código C++. En particular, pitón guepardo. Básicamente insertas código python dentro de tu código C++ y ejecutas el preprocesador cheetah. Esto permite hacer cálculos bastante complejos mucho más fácil que usar plantillas o preprocesador C++, además de obtener todas las extensiones y extensiones de python. por otro lado, hace que la depuración sea más difícil si algo sale mal. Si está interesado, podría proporcionar algunos ejemplos y el modo Emacs para editar programas Cheetah C++.

Si necesita algo menos potente y desea mantenerse dentro de C++ C solamente, eche un vistazo al preprocesador de impulso, here. Se necesita un poco de tiempo para acostumbrarse a él, pero podría hacer la vida muy fácil cuando el código repetitivo participa

bien, estoy pegando ejemplo guepardo, dame unos minutos:

#if defined (__INTEL_COMPILER) 
#pragma vector aligned 
#endif 
     for(int a = 0; a < $N; ++a) { 
      /// for functions in block 
%for ii, (fi,fj) in enumerate(fb) 
%set i = ii + ifb 
/// can also use (ix,iy,iz)=fi[0:2], need to clean up when not lazy 
%set ix = fi[0] 
%set iy = fi[1] 
%set iz = fi[2] 
%set jx = fj[0] 
%set jy = fj[1] 
%set jz = fj[2] 
      q$(i) += Ix(a,$(ix),$(jx))*Iy(a,$(iy),$(jy))*Iz(a,$(iz),$(jz)); 
%end for 
      /// end for functions in block 
     } 

produce (después de ejecutar cheetah ...)

#if defined (__INTEL_COMPILER) 
#pragma vector aligned 
#endif 
     for(int a = 0; a < 6; ++a) { 
      q0 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,0,0); 
      q1 += Ix(a,1,1)*Iy(a,0,0)*Iz(a,0,0); 
      q2 += Ix(a,0,1)*Iy(a,1,0)*Iz(a,0,0); 
      q3 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,1,0); 
      q4 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,0,0); 
      q5 += Ix(a,1,0)*Iy(a,0,1)*Iz(a,0,0); 
      q6 += Ix(a,0,0)*Iy(a,1,1)*Iz(a,0,0); 
      q7 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,1,0); 
      q8 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,0,1); 
      q9 += Ix(a,1,0)*Iy(a,0,0)*Iz(a,0,1); 
     } 

que es un C normal ++ código

líneas que comienzan con% se interpretan como declaraciones pitón por pre guepardo procesador. /// son comentarios de guepardo. Los valores predeterminados usan # como instrucciones python, pero las cambié para evitar colisiones con las directivas del preprocesador C. %end se debe usar para terminar bloques Python. Las variables en código C++ que comienzan con $ son reemplazadas por variables de python.

¿Desea ejemplos con el preprocesador de impulso?

+0

Por favor explique más. – anon

+0

He estado haciendo algo similar a esto usando Mako; Encontré esto mientras buscaba una alternativa más estándar. –

0

La generación de código es la mejor respuesta ...

También debe buscar la forma en que el kernel de Linux no listas enlazadas.

Linux Kernel Linked List Explained

La idea básica es que en lugar de tener su tipo empotrado en alguna estructura (digamos con los punteros next y prev, para una aplicación típica lista), que tiene la estructura lista del kernel incorporado en su estructura .. . Tipo de mente inclinada, pero mira el artículo ... Nunca pensé que los medicamentos genéricos seguros fueran posibles en C hasta que vi esto ....

+0

Excepto que su ejemplo no es seguro, es de tipo ajeno. – rlbond

+0

bien, bueno, no hay casting involucrado de todos modos ... :) – dicroce

+0

el casting está oculto detrás de algunas macros. Sin embargo, para C, donde es difícil o quizás imposible hacer este tipo de cosas de una manera segura, esta técnica es bastante útil. Windows también ha tenido macros similares ('CONTAINING_RECORD()') para la manipulación de listas vinculadas. Es una técnica agradable dadas las limitaciones de C. Y ahora he aprendido un nuevo término útil: "escriba inconsciente". –

2

La mayoría de la gente insiste en tratar de metaprogramar desde dentro de su idioma favorito. C++ se presenta como el ejemplo por excelencia debido a la metaprogramación de plantillas. Mientras funciona, es doloroso y torpe. Lo encuentro diciéndole a la gente que se dio cuenta de que era capaz de Turing, después de que Stroustrop lo añadiera al idioma; No creo que incluso él esperara que resultara de la manera en que lo hizo, aunque dudo que se queje ahora.

Pero la mayoría de los lenguajes de programación no tienen instalaciones de metaprogramación. (O pueden tener capacidades débiles o torpes :)

Una manera de evitar esto es hacer metaprogramación desde fuera de el idioma, usando program transformation tools. Estas herramientas pueden analizar el código fuente y realizar transformaciones arbitrarias en él (eso es lo que hace la metaprogramación de todos modos) y luego escupir el programa revisado.

Si tiene un sistema de transformación de programa de propósito general, que puede analizar lenguajes arbitrarios, puede hacer metaprogramación en/con el lenguaje que desee. Vea nuestra DMS Software Reengineering Toolkit para una herramienta de este tipo, que tiene extremos frontales robustos para C, C++, Java, C#, COBOL, PHP y una cantidad de otros lenguajes de programación, y se ha utilizado para la metaprogramación en todos estos.

Este enfoque es útil porque proporciona un enfoque metodológico regular para proporcionar métodos de metaprogramación para cualquier lenguaje que desee manipular. Y no tiene que esperar a que los diseñadores e implementadores de lenguaje lo implementen, ni tiene que vivir con las limitaciones de lo que pueden imaginar o implementar realmente, ni pagar el precio de espacio/tiempo de tiempo de ejecución de todos los datos reflexivos que toma para apoyarlo.

Y la transformación de programas es más poderosa que la metaprogramación de plantillas C++, ¡a pesar de que TM es capaz de Turing! La razón es que TM puede generar código arbitrario a partir de las plantillas, pero no puede modificar el código que no corresponde a la plantilla. Las transformaciones de programa pueden simular TM si insistes, y al menos es igual de fuerte, pero también puede llevar a cabo cambios arbitrarios en el código no de plantilla. Por lo tanto, estrictamente más poderoso.

Al igual que TM, el uso de transformaciones de programa requiere cierto esfuerzo para aprender y aplicar. Pero ser capaz de manipular programas de manera arbitraria parece bastante útil.

(Hemos hecho la reingeniería de arquitectura de aplicaciones C++ muy grandes usando DMS. TM simplemente no puede hacer esto).

+0

Vea también http://stackoverflow.com/a/21358087/120163 –

0

Si C++ 0x es una opción, algunos problemas de metaprogramación de plantillas se pueden reducir a un conjunto de funciones constexpr ejecutadas en tiempo de compilación. Por ejemplo, considere compile-time regex matcher using constexpr. Las funciones constexpr también son faster que los metaprogramas de plantillas C++.

Si está interesado en la programación funcional, existen otras opciones disponibles.

C++ Template Metaprogramming with Embedded Haskell

Meta Towards a Functional-Style Interface for C++ Template Metaprograms

Papers by Abel Sinkovics