template metaprogramming 101: desmystifying c++ metaprogramming

Post on 26-May-2015

294 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

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?

top related