2011-01-11 11 views
5

He estado usando metaprogramación bastante, pero a veces la combinación de macros y plantillas c simplemente no es suficiente.¿Hay alternativas de metaprogramación en C++ además de plantillas?

supongo que el inconveniente sería potencialmente falta de compatibilidad entre plataformas si la plataforma metaprogramming es sólo para, por ejemplo, Linux, etc.

Así que sí, ¿existe tal cosa disponible en este momento, además de plantillas? La metaprogramación de la búsqueda de Google está dominada por la metaprogramación de plantillas, por lo que es difícil de encontrar en este momento ...

edit: aquí hay un ejemplo de algo en lo que he estado trabajando.

Supongamos que tengo una clase genérica para guardar/cargar archivos en y desde búferes. Llamémoslo FilePack.

Tengo un definen macro, que se parece a

defineFilePack(BaseClass, "code-a") 

Básicamente crea una clase llamada "BaseClassPack", que se define como una subclase. Debajo está esa cosa.

class FilePack{ 
    public: 
     char * thebuffer; 
     int bufsize; 
     string packcode; 

     // and constructors etc 
     FilePack(const string& thecode, int bufsize); 
     void operator=(FilePack& rhs); 
     void saveToFile(const string& filename); 
     void loadFromFile(const string& filename); 
     // .. and all the function you'd expect to see in a class like this 

}; 

// the person details 

class PersonDetails{ 
    public: 
     solidstring<64> name; 
     int age; 
     DateTime birthday; 
     // .. yada yada yada 
}; 


defineFilePack(PersonDetails, "psd") 

// the above creates the following class 

class PersonDetailsPack : public FilePack{ 
    public: 
     PersonDetailsPack(): 
     FilePack("psd", sizeof(PersonDetails)){ // etc 

     } 

     PersonDetails& get(){ 
     return *(PersonDetails*)getBuffer(); 
     } 

     // and a lot more convenience function 

}; 

Ahora, hay en realidad un cheque en-construido por el constructor de FilePack que el código declarado coincida con el tamaño, el uso de un mapa global.

En este momento estoy perplejo sobre cómo hacer eso mediante la metaprogramación de plantillas, que en realidad es una buena opción porque todos estos códigos de paquete de archivos están declarados dentro del archivo fuente. Claro, alguien probablemente pueda hacer su propio FilePack en tiempo de ejecución, pero eso es además del punto.

Otra cosa con la que la metaprogramación podría ayudar es respaldar la carga de diferentes versiones de FilePack. Supongamos que tengo que actualizar la clase PersonDetails. Solo hago una nueva clase, uso algún tipo de metaprogramación para declarar la herencia y, por arte de magia, hago que FilePack sepa que cuando está cargando una versión anterior de PersonDetails puede llamar a la función de conversión, o lo que sea.

Además, le invitamos a comentar sobre esa arquitectura, y me gustaría escuchar algún comentario al respecto, pero podría estar un poco fuera de tema?

+0

¿Puede darnos un ejemplo de algo donde las plantillas + macros no son suficientes? Este sería un buen punto de partida para la discusión. –

+2

@David Rodriguez: por ejemplo, genera código que serializa clases a través de una conexión de red o que, en general, hace algo por cada miembro. – 6502

+0

"pero a veces la combinación de macros y plantillas c simplemente no es suficiente" - ¿qué es lo que falta/no es suficiente? – Naveen

Respuesta

5

También puede metaprogramar con el preprocesador.

Podría considerar el uso de preprocesadores de propósito especial para generar código también como "metaprogramación". Entonces podrías incluir cosas como lex/yacc y Qt MOC.

+0

Esa cosa de MOC es lo que estaba buscando, lástima que sea QT:/pero en concepto parece ser lo más práctico en este momento ... ¿Eso probablemente cuenta como lenguaje en la cima de un lenguaje, supongo? – kamziro

+0

No veo por qué es "demasiado malo es Qt". ¡Creo que Qt es excelente para lo que está hecho y más! –

1

Creo que este trabajo es perfecto, por ejemplo, para Python. La manera más fácil es usar un formato de archivo personalizado para describir cómo se crean las clases y luego puede generar tanto la implementación como la interfaz (incluso en varios idiomas).

Analizar los archivos de encabezado existentes de C++ es una especie de pesadilla debido a la compleja sintaxis de C++ ... (¿y por qué limitarse a lo que desea expresar?).

Python es multiplataforma y un muy buen lenguaje per se ...

Como ejemplo, el siguiente es un ejemplo de "aumentada" C++ he usado ...

// 
// U8 -> F32 format converter 
// 
// - src(Image:U8) ............ source image 
// - dst(pImage:F32:src) ...... destination image 
// 
ImgFilter u8_to_f32(Image& src, Image& dst) 
{ 
    const double k = 1.0/255; 
    for (int y=0; y<src.h; y++) 
    { 
     unsigned char *rp = src.u8(0, y); 
     float *wp = dst.f32(0, y); 
     for (int x=0,w=src.w; x<w; x++) 
      *wp++ = *rp++ * k; 
    } 
} 

El comentario sobre la función y el nombre/parámetros son leídos por un script en Python que genera el .h para la función de código, C++ que se encarga de la asignación de memoria, tamaño y compatibilidad de formatos de cheques, comandos argumento de la línea de análisis, ayuda en línea y un enlace de pitón. Básicamente puedo escribir solo la "carne" y tener todo el modelo generado para mí. La secuencia de comandos python haciendo esto es de 200 líneas y, dada la cantidad de código generado, la regla repetitiva de C++ para solo un par de filtros ya es más que eso.

+1

+1 para contrarrestar el downvote anónimo e inexplicable de drive-by. –

+0

Hace mucho tiempo, decidí ignorar las plantillas de C++, son las mejores en la mafia del mundo con las que es imposible hacer un razonamiento lógico en lo que es bueno hacer con las plantillas (muchas cosas) y lo que no (muchas otras cosas). Hace años que mi principal preocupación no es luchar entre las incompatibilidades de los compiladores en las áreas oscuras de la sintaxis de C++ y realmente no me pierdo esos momentos. – 6502

+0

Es probable que hayas votado negativamente porque el chico leyó "este trabajo es perfecto para Python", y de inmediato te lee como un duende o algo por el estilo. Me gusta ese enfoque, pero en realidad parece mucho trabajo. Eso es como hacer un lenguaje sobre C++ que aún funcione con material existente ... eso sería increíble. – kamziro

2

Dentro del lenguaje, solo puede usar plantillas o macros para metaprogramar. Las instalaciones de metaprogramación ofrecidas por, digamos, la biblioteca Boost Preprocessor, que implementa algunas cosas realmente sorprendentes como macros, son extremadamente poderosas.

Sin embargo, si quiere obtener un poco más por ahí, puede usar un lenguaje de scripts de su elección para metaprogramar.

+0

Siempre me he preguntado cómo aumentan sus cosas. Nunca los he usado realmente, pero parece que hay muchas cosas arcanas dentro de ellos. – kamziro

2

Si define metaprogramming como la escritura de código que genera el código, entonces usted tiene

  • plantillas.
  • El preprocesador.
  • Otro preprocesamiento (generalmente scripts, pero a veces extensión del compilador)
  • Generación de código fuente en C++ a partir del código C++, compilación sobre la marcha, carga como lib compartido.
  • Posiblemente, pero eso es estirarlo, también genera código de máquina, como trozos de trampolín.

Creo que lo más interesante que no esté plantilla o C++ preprocesador, es extensiones de lenguaje de programación que soportan la preocupación cruz, aspect-oriented programming, al igual que, la tala método de llamadas o de serialización.

Según recuerdo, ParcPlace creó una herramienta para eso?

Hm, eso me recuerda no olvidar echarle un vistazo, alguna vez. :-)

Saludos & HTH.,

+0

Consulte mi respuesta sobre los sistemas de transformación de programas, que generalizan la programación orientada a aspectos. Los aspectos solo proporcionan formas muy limitadas de modificar su código, y ese sentido son como plantillas, que también proporcionan una forma limitada (pero diferente). Los sistemas de transformaciones de programa pueden llevar a cabo modificaciones arbitrarias; usted está limitado por sus ambiciones y capacidad para expresar lo que quiere hacer, en lugar de lo que puede hacer la técnica específica de metaprogramación. –

0

Si desea realizar la manipulación arbitraria de código, que desea una finalidad herramientas generales metaprogramación tales como un sistema de transformación de programas. Estas herramientas aceptan el código fuente y llevan a cabo análisis/modificaciones arbitrarios de ese código de acuerdo con sus necesidades, utilizando tecnología similar a un compilador.

Nuestro DMS Software Reengineering Toolkit es exactamente ese sistema. Se parametriza mediante una descripción explícita del lenguaje de programación que se va a procesar y de la tarea que se desea llevar a cabo en el código fuente. DMS es único en ser genérico de esta manera (Jackpot es un sistema de transformación de programa solo en Java), y doblemente único en tener un robusto C++ Front End que se ha utilizado para tareas de transformación a gran escala en el sistema de producción C++.

Con una interfaz, DMS puede analizar el código fuente para sintaxis abstractas, compilar tablas de símbolos, ejecutar coincidencias de patrones o transformaciones de código utilizando patrones escritos directamente en C++ y regenerar código fuente compilable con comentarios y los formatos originales de literales (completos con número radix, etc.). La modificación de su programa puede ser cualquier cálculo que pueda definir sobre AST. En resumen, puede hacer, desde fuera del lenguaje, lo que las funciones de metaprogramación soportadas por el lenguaje no pueden hacer.

Cuestiones relacionadas