¿Es todo uso de plantillas en la metaprogramación de C ++?

8

Estoy tratando de entender qué metaprogramación es general y qué es en C ++ en particular. Si busco metaprogramación en c ++, obtengo tutoriales de metaprogramación de plantilla (TMP), pero no se explica si solo clasifica un uso específico de plantillas o todos los usos de las plantillas.

Mi pregunta es si todos los usos de plantillas en C ++ están categorizados como metaprogramación. Una explicación de por qué es o no también sería útil. Gracias.

joaerl
fuente
1
Compare con las macros CL y vea la décima regla de Greenspun. en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
marcado
1
TMP no es la única forma de metaprogramación. También se puede hacer metaprogramación con macros (uhh) y funciones constexpr . Constexpr puede ser más fácil de implementar que TMP.
zett42
1
@ zett42 No estoy seguro de si simplemente ejecutar código en tiempo de compilación es lo que debería considerarse "metaprogramación". Porque eso no es programación , sino informática. Simplemente está cambiando la ejecución del tiempo de ejecución al tiempo de compilación. La metaprogramación en C ++ es diferente a eso, porque genera código (plantillas, macros).
Johannes Schaub - litb

Respuestas:

2

Mi pregunta es si todos los usos de plantillas en C ++ se clasifican como metaprogramación.

No.

No todos los usos de plantillas, en C ++, son metaprogramación.

Obviamente es una cuestión de definiciones pero, en C ++, "metaprogramación" es sinónimo de "cómputo en tiempo de compilación".

Entonces, con las plantillas hacemos metaprogramación (específicamente la metaprogramación de plantilla) pero no todos los usos de las plantillas son metaprogramación.

Un simple contraejemplo

template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
 { std::cout << k << ": " << v << std::endl; }

Lo anterior printKeyVal()es una función de plantilla que imprime, en salida estándar (tiempo de ejecución, no tiempo de compilación), un par de valores genéricos.

No puede ejecutar el tiempo de compilación, por lo que es "plantilla" pero no es "metaprogramación".

Más en general: std::vectores una clase de plantilla que usa asignación de memoria. Y la asignación de memoria (hasta C ++ 17; tal vez en el futuro puede ser diferente) no se puede usar en código de tiempo de compilación.

Entonces std::vector(al contrario de std::arrayeso, tener un tamaño fijo, no usa asignación de memoria) es una característica de plantilla que no se puede usar (cuando el uso involucra la creación de instancias de un std::vectorobjeto) para la metaprogramación.

max66
fuente
Aún así, cualquier función que dependa de la plantilla requiere al menos algo de metaprogramación. En su ejemplo, printKeyValse define durante el tiempo de compilación de acuerdo con los argumentos con plantilla
SomeWittyUsername
Cuando programa, escribe código. No "computas" las cosas. Entonces definiría "metaprogramación" como "escribir código para escribir código". Y esto es exactamente de lo que se trata cada plantilla. Soy consciente de que la metaprogramación de plantillas a menudo se usa para el "cálculo del tiempo de compilación", pero yo personalmente usaría un término diferente para eso (estoy seguro de que no lo he hecho en el pasado, así que disculpas).
Johannes Schaub - litb
@ JohannesSchaub-litb: es cuestión de lenguaje y definiciones (y tengo la desventaja adicional de que no conozco bien el idioma inglés) y estoy de acuerdo en que es posible una definición de "metaprogramación" que incluya todas las plantillas y tal vez también razonable. Lo que digo es que, en la comunidad C ++, el término "metaprogramación" se usa con un significado diferente que se cruza pero no incluye todos los usos de la plantilla. Tal vez me equivoque ... podría ser una encuesta interesante.
max66
Tal vez se llama "metaprogramación" solo si el código de la plantilla no está duplicado 1: 1 para cada tipo, porque si está duplicado 1: 1, entonces el código de la plantilla es puramente pasivo y el compilador realiza toda la "metaprogramación" . Si hay alguna especialización o envío estático o de sobrecarga o algo así, es el código en sí mismo el que decide qué se generará. Esta parece ser la postura de D
Johannes Schaub - litb
@SomeWittyUsername: me parece que está utilizando una definición de "metaprogramación" que, perfectamente legítima y tal vez también razonable, es diferente de la que la comunidad de C ++ es, de facto, usando: hablando en voz baja: "metaprogramación == tiempo de compilación de ejecución ". Quizás estoy equivocado y la comunidad usa principalmente una definición que incluye todos los usos de plantillas ... podría ser una encuesta interesante, supongo.
max66
1

¿Qué es TMP en C ++?

La metaprogramación de plantilla (TMP) en C ++ es una técnica para expresar y ejecutar algoritmos arbitrarios en tiempo de compilación utilizando plantillas de C ++. Por lo general, se habilita mediante el uso de la especialización de plantillas para emular ramas condicionales y la definición recursiva de plantillas para emular bucles. El ejemplo más conocido es un cálculo factorial en tiempo de compilación:

template <unsigned int n>
struct factorial {
    // recursive definition to emulate a loop or a regular recursion
    enum { value = n * factorial<n - 1>::value };
};

// specialization that describes "break" condition for the recursion
template <>
struct factorial<0> { 
    enum { value = 1 };
};

que utiliza las dos técnicas mencionadas anteriormente.

Sin embargo, un uso mucho más común es el uso de TMP para la detección y transformación de tipos en lugar del cálculo numérico real, por ejemplo, una std::is_pointerutilidad estándar ( fuente ):

// generic definition that emulates "false" conditional branch
template<class T>
struct is_pointer_helper : std::false_type {};

// a specialization that emulates "true" conditional branch
template<class T>
struct is_pointer_helper<T*> : std::true_type {};

template<class T>
struct is_pointer : is_pointer_helper< typename std::remove_cv<T>::type > {};

La mayoría de las utilidades proporcionadas por el encabezado type_traits estándar se implementan utilizando técnicas TMP.

Dado que los algoritmos TMP se expresan usando definiciones de tipo, vale la pena mencionar que TMP es una forma de programación declarativa en la que la lógica de cálculo se expresa sin el uso de declaraciones explícitas de control de flujo ( if, else, for, etc ...).

¿Es todo el uso de plantillas C ++ una metaprogramación?

La respuesta corta es: No. Si las plantillas no se usan para expresar un algoritmo de tiempo de compilación, entonces no es una metaprogramación, es una programación genérica .

El objetivo principal de la introducción de las plantillas en C ++ era permitir la programación genérica, que es permitir la reutilización de los mismos algoritmos ( find, copy,sort , etc ...) y estructuras de datos ( vector, list, map, etc ...) para cualquier tipo, incluyendo el usuario definidos, que satisfacen ciertos requisitos.

De hecho, TMP en C ++ era descubrió por accidente y no era el uso previsto de plantillas.


En resumen: la metaprogramación de plantillas en C ++ es el uso de plantillas para expresar un algoritmo en tiempo de compilación, la mayoría (¿todos?) Otros usos de las plantillas de C ++ es una forma de programación genérica.

r3mus n0x
fuente
0

Estoy tratando de entender qué metaprogramación es general y qué es en C ++ en particular

No has dicho lo que entiendes por metaprogramación en general , por lo que sus respuestas no tienen un punto de partida común.

Voy a asumir la definición de Wikipedia es lo suficientemente bueno para esto:

La metaprogramación es una técnica de programación en la que los programas de computadora tienen la capacidad de tratar a otros programas como sus datos.

... se puede usar para mover cálculos del tiempo de ejecución al tiempo de compilación, para generar código usando cálculos de tiempo de compilación ...

C ++ generalmente no permite código auto modificable, así que lo estoy ignorando. También elijo no contar el preprocesador, ya que la sustitución textual en (o posiblemente justo antes) del tiempo de compilación no es lo mismo que operar en la semántica del programa.

Mi pregunta es si todos los usos de plantillas en C ++ se clasifican como metaprogramación

No, no es.

Considere, como referencia:

#define MAX(a,b) ((a) > (b) ? (a) : (b))

que es la forma más amplia de escribir un genérico (independiente del tipo) max sin usar plantillas. Ya he dicho que no cuento el preprocesador como metaprogramación, pero en cualquier caso siempre produce un código idéntico cada vez que se usa.

Simplemente delega el análisis de ese código y se preocupa por los tipos y si a>bestá definido para el compilador, en una fase de traducción posterior . Nada aquí opera en tiempo de compilación para producir un código resultante diferente dependiendo de ... cualquier cosa. Nada, en tiempo de compilación, se calcula.

Ahora, podemos comparar la versión de la plantilla:

template <typename T>
T max(T a, T b) { return a > b ? a : b; }

Esto no solo realiza una sustitución textual. El proceso de creación de instancias es más complejo, se pueden considerar reglas de búsqueda de nombres y sobrecargas, y en cierto sentido diferentes instancias pueden no ser equivalentes textualmente (por ejemplo, uno puede usar bool ::operator< (T,T)y otrobool T::operator<(T const&) o lo que sea).

Sin embargo, el significado de cada instanciación es el mismo (suponiendo definiciones compatibles deoperator< diferentes tipos, etc.) y no se calculó nada en el momento de la compilación, aparte del proceso habitual (mecánico) del compilador de resolver tipos y nombres, etc.

Por otro lado, definitivamente no es suficiente que su programa contenga instrucciones para que el compilador le diga qué hacer , porque eso es toda la programación.

Ahora, hay casos marginales como

template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };

el cual hacer avanzar un cálculo de tiempo de compilación (y en este caso un no-terminación de uno ya que no puedo ser molestado a escribir el caso de terminales), pero podría decirse que están no metaprogramming.

Aunque la definición de Wikipedia menciona los cálculos en movimiento para compilar el tiempo, esto es solo un cálculo de valor, no es una decisión en tiempo de compilación sobre la estructura o la semántica de su código.

Inútil
fuente
-1

Al escribir funciones de C ++ con plantillas, está escribiendo "instrucciones" para que el compilador le diga qué hacer cuando encuentre llamadas de la función. En este sentido, no está escribiendo código directamente, por lo tanto, lo llamamos metaprogramación.

Entonces, sí, cada código C ++ que involucra plantillas se considera metaprogramación

Tenga en cuenta que solo las partes que definen plantillas, funciones o clases son metaprogramación. ¡Las funciones y clases regulares se clasifican como C ++ regular!

Xatyrian
fuente
1
Cuando escribo "cp a.txt b.txt" en Bash, esto no está programando aunque estoy usando un entorno de programación completo. Del mismo modo, cuando lo uso, le std::vectordoy instrucciones a un compilador para que produzca un programa (por lo tanto, es meta), pero la instrucción en sí misma no es un programa. La mayoría de las personas no consideran el uso de macros "metaprogramación".
n. 'pronombres' m.
1
¡Tu respuesta es simplemente incorrecta! ¡Lea las otras respuestas dadas en este hilo para obtener una comprensión básica de lo que significa MTP!
Klaus
1
Cada vez que escribe C ++ sin plantillas, está escribiendo instrucciones para el compilador. Entonces, el hecho de que las plantillas le digan al compilador qué hacer, no puede ser suficiente para distinguir la programación de la metaprogramación
inútil el
1
@ JohannesSchaub-litb En el contexto de C ++, el término "metaprogramación" tiene un significado específico que difiere de su significado general . IIRC inicialmente se refirió a la característica descubierta de C ++ acuñada por A.Alexandrescu en su libro Modern C ++ Design . El uso clásico de la plantilla en C ++ no es metaprogramación (a menos que use el término metaprogramación no C ++).
YSC
1
De la pregunta de OP: "Estoy tratando de entender qué metaprogramación es general y qué es en C ++ en particular" . Así que supongo que su ángulo está bien y constituiría una excelente respuesta. Pero este no lo es. -1
YSC