¿Las plantillas de C ++ son solo una especie de macros glorificadas?

27

De diferentes comparaciones entre plantillas C ++ y genéricos C # / Java como este:

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

Percibí que las plantillas de C ++ se implementan mediante algún tipo de preprocesamiento (reemplazo de texto sin formato antes del análisis), no compilando. Debido a que la comprobación de tipos en las plantillas de C ++ se parece a las macros de C. Quiero decir, si hay algunos errores, son errores del código generado después de procesar bloques de código con plantilla, no de las plantillas en sí. En otras palabras, son solo una especie de versión superior de macros en C.

Luego encontré algunos otros hechos que respaldan esto.

  • Pensé que si las plantillas de C ++ se implementan mediante preprocesamiento, habrá problemas con la vinculación dinámica (usando .dll). Y una búsqueda rápida en Google lo apoyó.

  • Otro punto es que las constantes enteras se pueden pasar como argumentos a las plantillas. E incluso admite algún tipo de recursión. Pero esta recursión no se encuentra en el ensamblado compilado / código de máquina. Lo de la recursividad se gestiona en tiempo de compilación al generar funciones para cada llamada recursiva y, por lo tanto, tener un binario ejecutable más grande pero más rápido.

Aunque a diferencia de las macros C, tiene algunas habilidades superiores. ¿Pero no se implementa la plantilla C ++ con algún tipo de preprocesamiento? ¿Cómo se implementa esto en diferentes compiladores de C ++?

Gulshan
fuente
19
No Se compilan las plantillas de C ++.
Edward Strange
2
¿Cuál es su definición de "preprocesamiento"? ¿Y de "compilar"? Una definición suficientemente amplia de "preprocesamiento" podría incluir todo lo que hace un compilador; después de todo, un compilador realmente solo procesa la fuente antes de que se ejecute, ¿no?
James McNellis
@James McNellis en mi humilde opinión, si puede diferenciar el preprocesamiento de todas las otras cosas hechas para la compilación, es suficiente para entender mi pregunta. Para aclarar preprocesador- en.wikipedia.org/wiki/Preprocessor#Lexical_preprocessors
Gulshan
66
Si se refiere a esa forma de preprocesamiento, entonces no, las plantillas C ++ no son absolutamente una especie de macro glorificada.
James McNellis
1
El lenguaje de la plantilla se está completando, por lo que son mucho más que macros mejoradas.
davidk01

Respuestas:

9

Las plantillas de C ++ son una especie de macros tontas de Lisp (o incluso más, Scheme). Es un lenguaje completo de Turing que se evalúa en tiempo de compilación, pero está severamente limitado ya que no hay acceso desde ese lenguaje al entorno subyacente de C ++. Entonces, sí, las plantillas de C ++ pueden verse como alguna forma de preprocesamiento, con una interacción muy limitada con el código que se genera.

SK-logic
fuente
2
"pero está severamente limitado ya que no hay acceso desde ese lenguaje al entorno C ++ subyacente". -- ¿Qué significa eso? Traté de analizar esta declaración, pero fallé.
quant_dev
2
Uhm, en realidad ... github.com/kmichel/bf0x
Anton Golov
3
@ SK-logic: como comentario aparte, C ++ 11 es C ++, a menos que (pedante) trate diferentes versiones del mismo idioma como idiomas diferentes.
Jon Purdy
3
@ Jon Purdy, C ++ 11 no existía (oficialmente) en el momento de esta respuesta. Hoy en día, un ejemplo habría sido más complicado, como descomponer una estructura de datos, usar una función de biblioteca, etc.
SK-logic
1
@ SK-logic: ¿Conoces la implementación de C ++ con macros similares a Lisp? Me estoy cansando de las limitaciones de la plantilla. Un ejemplo de lenguaje de sintaxis de estilo C ++ con un potente sistema macro en Haxe: haxe.org/manual/macros . (No me ayuda porque uso C ++ para su propósito: programar microcontroladores de 8 bits; hay mejores lenguajes para cualquier otra cosa).
pfalcon
41

Probablemente la mayor diferencia es que las macros C se expanden en la fase de preprocesamiento, antes de que se realice cualquier otra compilación, mientras que las plantillas C ++ son parte de la compilación. Esto significa que las plantillas de C ++ son compatibles con el tipo y el alcance, entre otras cosas, y no son simples sustituciones textuales. Pueden compilar funciones reales y, por lo tanto, evitar la mayoría de los problemas que tienen las macros. Ser consciente de los tipos significa que pueden ser generales o especializados: por ejemplo, es fácil proporcionar una swapfunción de plantilla y escribir especializaciones que funcionen bien incluso si los objetos gestionan la memoria de almacenamiento dinámico.

Por lo tanto: las plantillas C ++ no están preprocesando en el mismo sentido que las macros, no son una especie de macro C y es imposible usar macros C para duplicar lo que hacen las plantillas.

Las plantillas viven en archivos de encabezado, no en bibliotecas vinculadas, es cierto, pero si está proporcionando un archivo .dll, presumiblemente también está proporcionando un archivo de encabezado para que lo use.

David Thornley
fuente
12
No necesitan vivir en el archivo de encabezado (esa es solo la técnica más simple para usarlos). Puede definirlos en un archivo fuente y forzar manualmente la creación de instancias de la plantilla en el archivo fuente (unidad de compilación). La vinculación recogerá las instancias normalmente (esta es una técnica para limitar plantillas a tipos específicos y no permitir todos los tipos genéricos).
Martin York
@ Martin: No estoy seguro de si esta técnica (aunque es compatible) es realmente explícitamente compatible con el estándar. De lo contrario, todos los compiladores ya se habrían exportimplementado. Sé que funciona para las funciones, pero dudo que funcione para las clases: ¿cómo conocerías su tamaño?
Matthieu M.
@Matthieu M: Esto no tiene nada que ver con la palabra clave de exportación. Se trata de la creación de instancias de plantilla "explícita" y está bien definida en el estándar.
Martin York
2
@Matthieu M .: Si el compilador conoce la firma de una función y el enlazador puede encontrar una implementación, todo está bien. Eso se aplica independientemente de si la función es una función de plantilla. En la práctica, generalmente viven en archivos de encabezado, porque forzar instancias específicas suele ser más trabajo de lo que vale, pero Martin tiene razón al señalar la alternativa.
David Thornley
Sé que funciona, seguro, para funciones especializadas. Sin embargo, también estoy bastante seguro de que no funciona para las clases, que era mi punto. Creo que también funciona para métodos de clases especializadas, pero no sé si esto es estándar o no.
Matthieu M.
5

¿Importa cómo se implementan? Los primeros compiladores de C ++ eran solo preprocesadores que alimentaban el código al compilador ac, no significa que C ++ sea solo una macro glorificada.

Las plantillas eliminan la necesidad de macros al proporcionar una forma más segura, más eficiente y especializable (incluso no creo que sea una palabra real) de implementar código para múltiples tipos.

Hay una variedad de formas de hacer código de tipo de plantilla en c, ninguna de las cuales es muy buena una vez que va más allá de los tipos simples.

Martin Beckett
fuente
No he dicho que C ++ sea una macro glorificada. Admiro mucho a C ++. Solo por ser curioso.
Gulshan
2
@Gulshan: No, no dijiste nada al respecto. Sin embargo, así es como funcionaban los primeros compiladores de C ++ (excepto que CFront era algo así como un compilador en lugar de solo un preprocesador de macros), y sus declaraciones sobre las plantillas de C ++ son aproximadamente aplicables a los primeros C ++.
David Thornley
CFront compiló C ++ a C. La línea entre el preprocesador y el compilador está claramente definida: un compilador intenta comprender su entrada, a través de análisis, creación de AST, etc.
Jon Purdy
1
Creo que lo que David quiso decir es que hay un subconjunto subyacente de C ++ y que las plantillas se pueden considerar como algún tipo de macros que se utilizan para generalizar un programa en este subconjunto, que luego se puede compilar como una etapa separada más.
Giorgio
5

Hay algunas diferencias; por ejemplo, las plantillas se pueden usar para crear instancias de una sobrecarga de funciones cuando sea necesario, mientras que con las macros, tendrías que expandir la macro una vez por cada posible sobrecarga para que sea visible para el compilador, por lo que terminarías con muchas de código no utilizado.

Otra diferencia es que las plantillas respetan los espacios de nombres.

Simon Richter
fuente
2

En mi humilde opinión, las plantillas C ++ y las macros C estaban destinadas a resolver dos problemas completamente diferentes. La Biblioteca de plantillas estándar de C ++ original era un mecanismo para desacoplar limpiamente las clases de contenedor (matrices, listas vinculadas, etc.) de las funciones genéricas que se les aplican comúnmente (como la ordenación y la concatenación). Tener representaciones abstractas de algoritmos eficientes y estructuras de datos conducen a un código más expresivo porque había significativamente menos conjeturas sobre la mejor manera de implementar una función que funcione en una determinada pieza de datos. Las macros de C estaban mucho más en línea con lo que normalmente se vería en las macros de Lisp, ya que proporcionaban un medio para "extender" el lenguaje con código en línea. Lo bueno es que la biblioteca estándar de C ++ extendió la funcionalidad de las plantillas para cubrir la gran mayoría de lo que usamos #define en C.

Bagazo
fuente