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.
Respuestas:
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
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::vector
es 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 destd::array
eso, 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 unstd::vector
objeto) para la metaprogramación.fuente
printKeyVal
se define durante el tiempo de compilación de acuerdo con los argumentos con plantilla¿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:
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_pointer
utilidad estándar ( fuente ):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.
fuente
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:
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.
No, no es.
Considere, como referencia:
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>b
está 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:
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 de
operator<
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
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.
fuente
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!
fuente
std::vector
doy 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".