Template metaprogramming 101: Desmystifying C++ metaprogramming

35
Template metaprogramming 101 Desmitificando la metaprogramación en C++ Manu Sánchez @Manu343726, Oct 2014

description

Slides from the first Template Metaprogramming 101 talk from Meeting C/C++ Madrid. http://www.meetup.com/Madrid-C-Cpp/events/205900412/

Transcript of Template metaprogramming 101: Desmystifying C++ metaprogramming

Page 1: Template metaprogramming 101: Desmystifying C++ metaprogramming

Template metaprogramming 101

Desmitificando la metaprogramación en C++

Manu Sánchez @Manu343726, Oct 2014

Page 2: Template metaprogramming 101: Desmystifying C++ metaprogramming

“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.

Page 3: Template metaprogramming 101: Desmystifying C++ metaprogramming

Modern C++ facts

Page 4: Template metaprogramming 101: Desmystifying C++ metaprogramming

● 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

Page 5: Template metaprogramming 101: Desmystifying C++ metaprogramming

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?).

Page 6: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 7: Template metaprogramming 101: Desmystifying C++ metaprogramming

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()

Page 8: Template metaprogramming 101: Desmystifying C++ metaprogramming

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()!

Page 9: Template metaprogramming 101: Desmystifying C++ metaprogramming

Metaprogramación

Page 10: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 11: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 12: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 13: Template metaprogramming 101: Desmystifying C++ metaprogramming

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?

Page 14: Template metaprogramming 101: Desmystifying C++ metaprogramming
Page 15: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 16: Template metaprogramming 101: Desmystifying C++ metaprogramming

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?

Page 17: Template metaprogramming 101: Desmystifying C++ metaprogramming

Metaprogramación en C++: Pitfalls

● typename ::type● <><<<>>>><><<<>>>::<<<>>>::<><>● template<template<typename> class > class● En resumen: Una sintaxis horrible.

Page 18: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 19: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 20: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 21: Template metaprogramming 101: Desmystifying C++ metaprogramming

Metaprogramación en C++

● Pero cuando funciona...

Page 22: Template metaprogramming 101: Desmystifying C++ metaprogramming

Compile-time computing

Page 23: Template metaprogramming 101: Desmystifying C++ metaprogramming

● ¿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

Page 24: Template metaprogramming 101: Desmystifying C++ metaprogramming

Cálculo en tiempo de compilación

● ¿Y qué pasa con constexpr? Una herramienta más. Mejor para unos casos y peor para otros.

Page 25: Template metaprogramming 101: Desmystifying C++ metaprogramming

Generación y manipulación de tipos

(y su código subyacente)

Page 26: Template metaprogramming 101: Desmystifying C++ metaprogramming

● 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

Page 27: Template metaprogramming 101: Desmystifying C++ metaprogramming

Typelists

● Como su nombre indica, son “listas” cuyos elementos son tipos.

● Muy fáciles de implementar gracias a las variadic templates.

Page 28: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 29: Template metaprogramming 101: Desmystifying C++ metaprogramming

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.

Page 30: Template metaprogramming 101: Desmystifying C++ metaprogramming

Metaprogramación de alto nivel

Page 31: Template metaprogramming 101: Desmystifying C++ metaprogramming

● Haskell, otra vez● foldl, foldr, filter, map, etc● Variadic templates: O(1) map, wow!

Metafunciones de alto nivel

Page 32: Template metaprogramming 101: Desmystifying C++ metaprogramming

Evaluación uniforme de expresiones

● tyename ::type es totalmente ilegible y escala pobremente.

● Mi propuesta: tml::eval

Page 33: Template metaprogramming 101: Desmystifying C++ metaprogramming

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>

Page 34: Template metaprogramming 101: Desmystifying C++ metaprogramming

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>>>>;

Page 35: Template metaprogramming 101: Desmystifying C++ metaprogramming

¿Preguntas?