2009-08-02 16 views
25

Me gustaría depurar algún código de plantilla para entenderlo mejor.
Desafortunadamente soy nuevo en metaprogramming plantilla y es difícil para mí conseguir enMetaprogramación de plantillas C++: ¿es posible generar el código generado?

Cuando trato de salida de los archivos de origen que se procesan consigo 125 000 líneas de código:./

Entonces, ¿hay una ¿De qué manera puedo ver el Código generado? (La biblioteca que estoy usando es SeqAn)

+2

No, pero debería ser. Alguien debería hacer esto como un proyecto de Clang: D –

+0

Tenga en cuenta que debido a [SFINAE] (https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error) el código que obtendría simplemente reemplazando cada plantilla con alguna alternativa codificada probablemente sea ilegal P.ej. siempre que nunca se llame, un método de una clase de plantilla bien puede llamar a cosas que no existen. – MvG

+1

@JosephGarvin Ahora hay un proyecto basado en Clang para esto. La última versión activa de [Templight, el generador de perfiles y creación de instancias de plantilla basado en clang] (https://github.com/mikael-s-persson/templight), [visualizador Templar] (https://github.com/ schulmar/Templar), así como también [Metashell] (https://github.com/sabel83/metashell). –

Respuesta

21

No, no lo es. El preprocesador no tiene nada que ver con el procesamiento de plantillas, que realiza el compilador. Las plantillas no generan código C++, como tampoco lo hace una llamada a función: son parte integral del lenguaje C++.

+0

Si bien esto es generalmente cierto, en teoría también es cierto para el preprocesador. En la práctica, la implementación más sencilla es generar código similar a C++ como el resultado de la etapa de preprocesador, pero no para las instancias de plantilla. Lo contrario sería irrazonablemente difícil pero técnicamente imposible. El principal problema está en las búsquedas de nombres, y el compilador podría generar nombres únicos durante las instancias de plantillas. – MSalters

+0

Para ser sincero, aún puede usar el depurador para mostrar el tipo calculado si lo instancia. Hice un ejemplo de cómo usar Visual C++. Lo usé para mis metaprogramas muy a menudo. – ovanes

5

Esto es potencialmente la respuesta a su pregunta:

C++ Template preprocessor tool

parece haber satisfecho la última persona que hizo - aunque no puedo imaginar por qué! El resultado de un compilador de C++ en C suele ser bastante ilegible, ya que no pretende ser una ayuda para la comprensión, sino simplemente un tipo de lenguaje ensamblador portátil.

1

En general, no es posible generar el código completo. Pero lo que encontré extremadamente interesante, es la capacidad de usar el depurador de Visual C++ para mostrarle el tipo. Tome ese metaprograma simple:

template<class Head, class Tail> 
struct type_list 
{ 
    typedef Head head; 
    typedef Tail tail; 
}; 

struct null_type 
{}; 

template<class List> 
struct list_head 
{ 
    typedef typename List::head head; 
}; 

template<class List> 
struct list_tail 
{ 
    typedef typename List::tail tail; 
}; 

template<class List> 
struct list_length 
{ 
    static const size_t length = 1+list_length< typename list_tail<List>::tail >::length; 
}; 

template<> 
struct list_length<null_type> 
{ 
    static const size_t length = 0; 
}; 


int main() 
{ 
    typedef 
    type_list 
    < int 
    , type_list 
     < double 
     , type_list 
     < char 
     , null_type 
     > 
     > 
    >  my_types; 

    my_types test1; 

    size_t length=list_length<my_types>::length; 

    list_head<list_tail<list_tail<my_types>::tail>::tail>::head test2; 

} 

Acabo de instanciar mis meta-tipos. Estas todavía son instancias de clase C++ vacías que tienen al menos 1 byte de longitud. Ahora puedo poner un punto de interrupción después de la última creación de instancias de test2 y ver, qué tipos/valores de longitud, test1 y test2 son de:

Esto es lo que muestra el depurador:

length 3 unsigned int 
test1 {...} type_list<int,type_list<double,type_list<char,null_type> > > 
test2 -52 'Ì' char 

Ahora que se conoce el head le devolvió un carácter, su lista contiene int, double, char y termina con null_type.

Eso me ayudó mucho. A veces es necesario copiar el tipo realmente desordenado a un editor de texto y formatearlo en un formato legible, pero eso le da la posibilidad de rastrear lo que está dentro y cómo se calcula.

Espero que ayude,
Ovanes

22

No, en general, no se puede hacer. Las plantillas son simplemente parte del lenguaje C++, no son un preprocesador por separado, por lo que no generan código C++.

La solución habitual es rociar su código con afirmaciones estáticas y otras pruebas para verificar que las plantillas correctas sean instanciadas de la manera correcta.

Una vez que comienza a perderse en su metaprogramming, este sencillo truco puede ayudar a determinar qué tipo de un parámetro de plantilla realmente es:

// given a variable t of an unknown type T 
int*** i = t; 

Cuando el compilador encuentra presente, que va a imprimir un bonito y sencillo mensaje de error "No se puede convertir <long, detailed typename> en int ***", lo que le permite verificar fácilmente que el parámetro de la plantilla T es en realidad el tipo que cree que debería ser.

14

Comprobar my publication on C++ template metaprogram debugging

de la página 6 se puede ver cómo funciona. Para fines específicos, no necesitará toda la cadena de herramientas, se puede hacer a mano.

He creado un complemento de Visual C++ en el que puede colocar puntos de interrupción, etc., pero era más una prueba de concepto que una herramienta para el uso diario.

Hemos estado trabajando en una interfaz gráfica que muestra todas las instancias, permite la depuración, creación de perfiles. Lamentablemente, no podemos prometer ninguna fecha de publicación para esa herramienta, ya que lo hacemos en nuestro tiempo libre bastante limitado.

ACTUALIZACIÓN: el depurador y perfilador está disponible here

ACTUALIZACIÓN: C++Now presentation

+0

¡Parece interesante! –

Cuestiones relacionadas