c++ - plantillas - programacion ats funciones
¿Cómo se depura el código con muchas plantillas en c++? (10)
Me resulta muy difícil averiguar qué está mal con mi código cuando uso la meta-programació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.
¿Qué consejos o consejos puede ofrecer al tratar de descubrir por qué algo no se está compilando, además de simplemente buscar el código manualmente y esperar que me llegue?
Metashell es una gran herramienta para la depuración de plantillas. Con el modo en línea!
¿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 proporcionando controles de cordura
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 aceptada erróneamente 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 tratar de no usar metaprogramación en todas partes . Es complicado, así que úselo solo cuando realmente lo necesite.
Esto debería ayudarte, creo.
http://www.bdsoft.com/tools/stlfilt.html
No lo he usado 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.
Para STL, al menos, hay herramientas disponibles que emitirán mensajes de error más amigables para los humanos. Ver http://www.bdsoft.com/tools/stlfilt.html
Para 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.
Si está usando 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.
Te acostumbras a él a medida que pasa el tiempo, y desafortunadamente si planeas usar C ++, tienes que hacerlo. 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 debes recordar que los buenos STATIC_ERRORS que puedes encontrar aquí y allá en código, son colocados por los autores donde las cosas comúnmente se rompen, y siempre habrá casos de esquina horribles, que el autor no contempló, que producirán 400 líneas de mensajes de error porque se perdió un const en algún lugar, 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 con C ++, se requiere experiencia y entrenamiento.
Como las respuestas ya lo ilustran, hay básicamente 2 tipos de dificultades en el código de la plantilla: 1. hacer que se compile y encontrar la causa de los errores del compilador 2. obtenerlo hace lo correcto durante el 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 luego sigue los consejos de las otras respuestas, especialmente la que dice compile_time, será más fácil encontrar la fuente de problemas.
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 generalmente consisten en probar una sección de código lo más pequeña posible hasta que los errores estén aislados. 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 las afirmaciones en tiempo de compilación para hacer que los problemas de uso sean un poco más fáciles de diagnosticar.
Templight : una plantilla de C ++ depurador y perfilador de metaprogramas