template metaprogramming 101: desmystifying c++ metaprogramming
DESCRIPTION
Slides from the first Template Metaprogramming 101 talk from Meeting C/C++ Madrid. http://www.meetup.com/Madrid-C-Cpp/events/205900412/TRANSCRIPT
Template metaprogramming 101
Desmitificando la metaprogramación en C++
Manu Sánchez @Manu343726, Oct 2014
“Modern C++”
● La mayoría de la industria todavía depende de e incluso desarrolla en C++98/03. El eterno problema del legacy code.
● No, no me refiero a Alexandrescu. “Modern C++” es una forma de diferenciar dicho legacy code del state of the art C++, C++11/14.
Modern C++ facts
● Hace mucho tiempo que un compilador dejó de ser un traductor de lenguaje de alto nivel a ensamblador.
● En los últimos veinte años ha habido una evolución increíble en el desarrollo e implementación de compiladores.
Los compiladores
Los compiladores
● Hoy en día es muy difícil optimizar a mano: Arquitecturas y lenguajes muy complejos. Pero -O3 lo hace muy bien por nosotros.
● Trabajar en ensamblador por eficiencia ya no tiene ningún sentido (Salvo casos muy concretos. ¿Fixed-point? ¿ISRs?).
Los compiladores
● Moraleja: Bajo nivel != eficiencia. Para la mayoría de los seres humanos bajo nivel == ineficiencia.
● Optimiza algoritmos y arquitectura del programa. Evita microoptimizaciones.
El lenguaje
● C++11 se siente como un nuevo y mejor lenguaje. C++14 arregla y mejora bastantes cosas. ¡Estoy deseando ver C++17!
● La mayoría de las “pifias” que uno tenía que hacer ya no son necesarias > >... ;)
● La programación en alto nivel y genérica con C++ es sencilla y natural. Java no es de alto nivel por Dios… std::copy()
El lenguaje
● Algunos argumentan que el lenguaje cada vez es más complicado. A nivel de “friki” es cierto, pero a nivel de usuario es bastante más sencillo: Nada de The Rule Of Five, The Rule Of Zero. ¡std::make_unique()!
Metaprogramación
Metaprogramación
● Generación contra duplicado de código.● Automatización de la generación de código.● Menos código == menos código que
mantener == menos bugs potenciales.
Metaprogramación en C++
● El sistema de plantillas de C++ es Turing Completo. Te ha quedado muy chula la frase, ¿pero eso qué demonios significa?
● Significa que tenemos a nuestra disposición un sistema de generación de tipos que es capaz de computar cualquier cosa. Utilicemoslo.
Metaprogramación en C++
● ¿Pero cómo es posible? Hay algo que tienen las plantillas y no los genéricos: Especialización. Y sobretodo, especialización parcial.
● En otras palabras, pattern matching.
Metaprogramación en C++
● Hasta ahora todo ha sonado muy bien, ¿por qué la gente le suele tener tanto miedo y acaba poniendo esta cara?
Metaprogramación en C++
● Hasta ahora todo ha sonado muy bien, ¿por qué la gente le suele tener tanto miedo y acaba poniendo esta cara?
● Muy sencillo: Su sintaxis y los mensajes de error.
Metaprogramación en C++
● Seamos sinceros, el lenguaje no estaba diseñado para hacer ésto, por mucho que recientes añadidos como las variadic templates o <type_traits> ayuden.
● ¿Cual es el resultado?
Metaprogramación en C++: Pitfalls
● typename ::type● <><<<>>>><><<<>>>::<<<>>>::<><>● template<template<typename> class > class● En resumen: Una sintaxis horrible.
Metaprogramación en C++: Pitfalls
● Esos mensajes de error tan cortos y que siempre van al grano.
● Compiladores como CLang han mejorado bastante en este asunto. Tanto que a veces lo que dice hasta puede llegar a ser útil.
● GCC sigue a lo suyo.
Metaprogramación en C++: Pitfalls
● Mi consejo: Lee la primera línea, olvídate del resto. Los errores suelen ir en cascada.
● Pero no os voy a mentir: Depurar no es nada fácil. static_assert(sizeof(T) != sizeof(T) , “Trace”) y herramientas como templight ayudan muchísimo.
Metaprogramación en C++: Pitfalls
● Rendimiento: Suele ser bastante malo, consume un montón de recursos, y es altamente dependiente del compilador. En algunos ni siquiera funciona, gracias Microsoft por tu maravilloso compilador.
Metaprogramación en C++
● Pero cuando funciona...
Compile-time computing
● ¿Qué significa hacer cálculos en tiempo de compilación?
● Significa que no quiero que el programa calcule absolutamente nada, quiero el resultado directamente grabado en el ejecutable. Literalmente.
Cálculo en tiempo de compilación
Cálculo en tiempo de compilación
● ¿Y qué pasa con constexpr? Una herramienta más. Mejor para unos casos y peor para otros.
Generación y manipulación de tipos
(y su código subyacente)
● Ya que estamos utilizando un sistema de generación de tipos, juguemos con tipos.
● Multitud de aplicaciones. Policy based designs. Generación de jerarquías.
● Definitivamente Alexandrescu se adelantó a su época.
Generación y manipulación de tipos
Typelists
● Como su nombre indica, son “listas” cuyos elementos son tipos.
● Muy fáciles de implementar gracias a las variadic templates.
Metafunciones
● Por “metafunción” se entiende una función que manipula y devuelve tipos.
● En el caso de tmp, normalmente son plantillas que “devuelven” un resultado a través de un tipo miembro público. ::type en la biblioteca estándar, ::result en mi Turbo.
Metafunciones
● En éste sentido, los type traits que provee la biblioteca estándar desde C++11 pueden entenderse como metafunciones.
● std::remove_const por ejemplo: Dado un tipo, lo devuelve sin su cualificador const superior. Es decir: remove_const(const int) -> int.
Metaprogramación de alto nivel
● Haskell, otra vez● foldl, foldr, filter, map, etc● Variadic templates: O(1) map, wow!
Metafunciones de alto nivel
Evaluación uniforme de expresiones
● tyename ::type es totalmente ilegible y escala pobremente.
● Mi propuesta: tml::eval
Evaluación uniforme de expresiones
● tml::eval es una metafunción que dada una expresión la evalua convenientemente.
● Una expresión puede ser: Un valor (tipo) simple: int, char, bool Una expresión compuesta: std::vector<int> Una metafunción: std::remove_const<int>
Evaluación uniforme de expresiones
● tml::eval<std::remove_reference<std::remove_const<const int&>>;
● tml::eval<tml::add<tml::Int<2>,tml::add<tml::Int<3>,tml::Int<5>>>>;
¿Preguntas?