2008-10-26 12 views
13

Esta pregunta existe porque tiene importancia histórica, pero no es considera un bien, en el tema de la pregunta para este sitio, así que por favor no lo use como prueba de que se puede pedir similares preguntas aquí.¿Cuáles son los mejores ejemplos de metaprogramación que ha visto en C++?

Más información: https://stackoverflow.com/faq


¿Cuáles son los ejemplos más frescas del metaprogramming que has visto en C++?
¿Cuáles son algunos usos prácticos de la metaprogramación que ha visto en C++?

+0

Creo que Boost Metaparse es algo realmente sorprendente https://github.com/boostorg/metaparse https://github.com/sabel83/metaparse_tutorial –

Respuesta

23

Personalmente, creo que Boost.Spirit es un ejemplo bastante sorprendente de meta-programación. Es un generador de analizador completo que le permite expresar gramáticas utilizando la sintaxis de C++.

+1

+1: spirit is very sick. Es posible que desee vincular a una versión más nueva de espíritu tal vez? Esta versión parece un poco vieja. – n1ckp

+0

@ n1ck: gracias, actualicé el enlace – Ferruccio

7

El mejor ejemplo de metaprogramación: engañar al compilador para que compute una lista de números primos. No es muy práctico, pero impresionante.

Un uso práctico son las sentencias assert de tiempo de compilación, es decir, que causan un error de compilación si una condición booleana no se cumple.

+0

+1 para aserción estática –

2

luabind es un ejemplo práctico muy bien, bastante agradable DSL unión de clases de C++ unión a LUA

19

El uso más práctico de programación meta está convirtiendo un error de ejecución en un error de tiempo de compilación.

Ejemplo: Permite llamar a la interfaz IFoo. Uno de mis programas trataba sobre un objeto COM que tenía múltiples rutas a IFoo (jerarquía de herencia muy complicada). Desafortunadamente, la implementación subyacente del objeto COM no se dio cuenta de que tenían múltiples rutas a IFoo. Supusieron que siempre era la izquierda más uno. Así que dentro de su código, el siguiente patrón era muy común

void SomeMethod(IFoo* pFoo) { 
     CFooImpl *p = (CFooImpl)pFoo; 
    } 

El segundo IFoo aunque causó el puntero "p" resultante sea completamente válido (herencia múltiple es peligroso).

La solución a largo plazo fue que el propietario del objeto COM solucionara este problema. A corto plazo, aunque necesitaba asegurarme de que siempre devolvía el IFoo correcto. Podría garantizar que tuve el IFoo apropiado al usar una QI y evitar cualquier conversión implícita a IFoo. Así que creé una nueva implementación de CComPtr <> y agregué la siguiente anulación al método igual.

template <typename T> 
CComPtr<T>& operator=(const T* pT) { 
// CComPTr Assign logic 
} 
template <> 
CComPtr<IFoo> operator=<IFoo>(const IFoo* pT) { 
    COMPILE_ERROR(); 
} 

Esto reveló rápidamente cada lugar que impliqué implícitamente a IFoo.

+1

QI = QueryInterface http://msdn.microsoft.com/en-us/library/ms682521(VS.85).aspx – JaredPar

+2

¿Esto es metaprogramación? Parece una especialización simple. – fizzer

+1

En muchos sentidos, la metaprogramación es especialización. Este es un ejemplo bastante simple de metaprogramación (pero muy efectivo). Creo que representa uno de los aspectos más prácticos de la metaprogramación, evitando que te lastimes a ti mismo. – JaredPar

12

Blitz++ hace algunas cosas impresionantes con las plantillas (por ejemplo, una sola línea de código legible se puede convertir en un conjunto de bucles en una matriz multidimensional, optimizada automáticamente para la mejor orden transversal).

+0

Wow. Me doy cuenta de que esto es un poco tarde, pero si tienes la oportunidad de señalar la línea en cuestión, sería genial. – Praxeolitic

+0

El enlace parece haber cambiado – TankorSmash

4

Tendría que decir Boost.Lambda, Boost.Function y Boost.Bind y la forma en que todos funcionan perfectamente juntos. Proporcionan una interfaz realmente ingeniosa y hacen que la programación funcional sea lo más fácil posible en un lenguaje que en realidad no fue creado.

+0

Todos estos ahora son nativos en C++ 11. – TankorSmash

0

Hice una pregunta no hace mucho tiempo: C++ Runtime Knowledge of Classes y la respuesta que obtuve de un usuario de StackOverflow "Denice" era una URL a un sitio web Meatspace: C++ runtime class registration.

Creo que es una forma genial de usar plantillas y crear instancias de objetos que se derivan de una clase base, de modo que cuando tengo 10 archivos C++, todos pueden simplemente agregar AUTO_REGISTER_BASE() en la parte inferior, y cuando todo está hecho y vinculado, solo aquellas clases/archivos que lo hicieron se registrarían, por lo que en tiempo de ejecución puede cambiar entre las diferentes clases que están disponibles, y las que no están disponibles no están registradas y por lo tanto no pueden ser accidentalmente llamado.

Hay muchas maneras diferentes de hacer notificaciones de eventos (select(), kqueue(),/dev/epoll, Solaris tiene su propia cosa, poll()), y necesitaba una forma de tener todo el Los archivos de clase existen en el directorio, pero dependiendo de qué sistema operativo se ejecutó Makefile, solo compilaría algunos. Necesitaba una manera de saber en tiempo de ejecución cuáles estaban disponibles, y tenía una forma para que el programador utilizara la biblioteca para seleccionar sus preferencias, sin embargo, si no estaba disponible, simplemente usaba el que tenía el sentido más lógico para la plataforma (cada uno tener pesos asignados a ellos).

El código anterior me ayudó a lograr este objetivo, con algunas modificaciones importantes, ¡pero me ayudó de todos modos!

12

No es de uso práctico (excepto tal vez para la prueba del compilador), pero metatrace es un Whitted-Style (es decir recursiva y determinista) ray tracer que genera imágenes como las del momento de compilación:

metatrace example

Algunas partes más complejas of the code se pueden ver en fixp.hh, que tiene una aplicación de sqrt de punto fijo utilizando el método de Heron, o sphere.hh que muestra cálculo ray/esfera-intersección.

Cuestiones relacionadas