2009-02-18 15 views
22

Me resulta muy difícil averiguar cuál es el problema con mi código cuando uso la metaprogramación de plantillas C++. Puede ser que no sea muy bueno entendiendo los mensajes de error, pero que yo sepa, no puedo recurrir a declaraciones impresas o puntos de interrupción para descubrir qué está pasando.¿Cómo se depura el código con muchas plantillas en C++?

¿Qué consejos o consejos puede ofrecer al tratar de descubrir por qué algo no se está compilando aparte de solo elegir el código manualmente y esperar que llegue a mí?

Respuesta

14

Para STL, al menos, hay herramientas disponibles que emitirán mensajes de error más amigables para el usuario. Ver http://www.bdsoft.com/tools/stlfilt.html

Para las plantillas que no sean STL, solo tendrá que aprender lo que significan los errores. Después de haberlos visto una docena de veces, es más fácil adivinar cuál es el problema. Si los publica aquí, tal vez alguien pueda ayudarlo a resolverlo.

7

Puede intentar usar un compilador más nuevo. Si está utilizando Visual C++ 6.0, cambie a 9.0 y verá un gran salto en la utilidad de los errores del compilador.

De lo contrario, mis técnicas usualmente han sido probar una sección de código lo más pequeña posible hasta que los errores se hayan aislado. Esta es probablemente la falla más grande del sistema de plantillas; no hay una manera sensata de depurarlas.

En su propio código, haga un uso liberal de compile-time asserts para hacer que los problemas de uso sean un poco más fáciles de diagnosticar.

+0

Puede usar afirmaciones de tiempo de compilación sin aumentar también. Detalles aquí: http://www.pixelbeat.org/programming/gcc/static_assert.html – pixelbeat

+0

En un entorno corporativo es posible que no pueda migrar lejos de VC6. –

+3

graham: una empresa que todavía obliga a sus empleados a usar VC6 es una empresa en la que no quiero trabajar, bajo ninguna circunstancia. Dándole esas herramientas inapropiadas muestra muy claramente que la compañía simplemente no se preocupa por usted. No es una relación sana. –

3

Esto debería ayudarte, creo.

http://www.bdsoft.com/tools/stlfilt.html

no he utilizado yo mismo; pero, podría ayudarte. También puedo decirte que a medida que obtengas más experiencia con plantillas y metaprogramas, te acostumbrarás a los mensajes de error. A veces pueden ser difíciles de leer; pero, hay lógica en su locura. Simplemente haga que su terminal sea lo más grande que pueda e intente traducir lo que está diciendo en su cabeza mientras lo lee.

3

¿Qué compilador estás usando? VC8 y 9 son realmente bastante decentes en la salida de mensajes de error legibles. Todavía se necesita un poco de paciencia, pero se puede hacer, y básicamente muestran el equivalente en tiempo de compilación de la pila de llamadas. Comenzando en la parte inferior, ¿qué instanciación de la plantilla causó el error y cuáles fueron los argumentos de la plantilla? El siguiente nivel muestra la plantilla desde la que se creó la instancia, y así sucesivamente, hasta llegar al nivel superior. Por supuesto, esto solo es visible en la pestaña de "salida", no en los "errores" que normalmente se muestran después de una compilación fallida.

El principio es similar en GCC, aunque la última vez que lo intenté, al menos, el formato era algo menos legible. Pero realmente, solo tiene que rastrear a través de la pila de instancias, y en cada nivel, verificar que se creó una instancia con los tipos que esperaba, hasta que encuentre el que introdujo el error.

Es un dolor, pero se puede hacer, y no requiere nada más que la paciencia y la voluntad de leer los mensajes de error. :)

Además, el uso liberal de static_assert (o BOOST_STATIC_ASSERT) puede ayudar mucho al proporcionar la cordura comprueba

2

que se acostumbre a ella como pasa el tiempo, y por desgracia, si usted planea usar C++, hay que . Porque, algunas bibliotecas como VC9 tienen buenos mensajes de error, pero tan pronto como te mueves para decir GCC, o algún otro compilador, los mensajes desaparecen.E incluso VC9 no te ayudará mucho cuando tengas errores de alguna biblioteca escrita por otra persona o por ti mismo durante una noche, incluso algunas bibliotecas de Boost no son tan amistosas. Simplemente porque no todos los autores se han tomado la molestia de aclarar las cosas cuando ocurre un error, y eso es aún más común con las nuevas bibliotecas (que tienden a tener la mayoría de los errores y menos ayuda).

También debe recordar que los buenos STATIC_ERRORS que puede encontrar aquí y allá en el código, son colocados por los autores donde las cosas comúnmente se rompen, y siempre habrá casos de esquinas horribles, que el autor no contempló, que produce 400 líneas de mensajes de error porque te perdiste un const en algún lado, por ejemplo.

Usar herramientas te ayudará al principio, pero te hará daño a largo plazo. Y dado que el problema es inherente a C++, no va a desaparecer en el futuro cercano. Y estas paredes de errores probablemente estarán con nosotros hasta que C++ ya no esté en uso. Entonces, las herramientas cortan tus dientes cuando los necesitas para sobrevivir. Si planea dejar C++ pronto, entonces siéntase libre de usarlos. Hoy en día, normalmente puedo entender esos mensajes de error de 400 líneas de un solo vistazo, por lo que son muy claros para mis ojos, pero eso no es gracias a ninguna herramienta.

Como con todo, especialmente en C++, se requiere experiencia y capacitación.

5

Si está utilizando gcc, he encontrado que colorgcc puede ayudar un poco. La codificación por colores facilita el análisis mental de las advertencias frente a los errores frente a la información contextual.

4

Al hacer algo complicado en el lenguaje de meta-programación, utilizo la macro BOOST_MPL_ASSERT varias veces, comprobando los resultados de cada paso de la meta-ejecución. La biblioteca Boost.MPL es muy útil para ese asunto. Le sugiero que use tanto código como sea posible, porque es probable que no contenga errores.

Cuando no estoy tan seguro de que se esté utilizando la especialización adecuada para una clase, tiendo a aislar la especialización correcta en un espacio de nombres. Una vez que esté seguro de que la especialización es válida, debe asegurarse de que se elija. Si no es así, debes averiguar cuál se elige en su lugar. Entonces recomendaría usar Boost.EnableIf para excluir esta especialización erróneamente aceptada del proceso de selección.

Por último, STLfilt es extremadamente útil y puede modificarlo usted mismo para que se adapte a sus necesidades lo mejor posible.

Pero lo más importante es intentar no usar la metaprogramación en todas partes. Es complicado, entonces úsela solo cuando realmente lo necesite.

2

Como ilustran las respuestas ya, hay básicamente 2 tipos de dificultades en el código de la plantilla: 1. para conseguir que se compile y encontrar la causa de los errores de compilación 2. conseguir que se haga hacer lo correcto en tiempo de ejecución

Normalmente trato de separar la magia del tipo de tiempo de compilación de la lógica de tiempo de ejecución, esto ayuda a encontrar la causa del problema (Tipo 1 o 2). Una forma de lograr esto es usar un tipo de plantilla para tipo magic y la menor funcionalidad de tiempo de ejecución posible, y un tipo simple para la lógica de tiempo de ejecución, que use el tipo de plantilla.

Si sigue los consejos de las otras respuestas, especialmente la de compile_time afirma, será más fácil encontrar la fuente de problemas.

1

Templight: A C++ plantilla metaprograma depurador y de perfiles de

0

Metashell es una gran herramienta para la depuración plantilla. Con el modo en línea!

Cuestiones relacionadas