El compilador generará código para cada instancia de plantilla cuando use una plantilla durante el paso de compilación. En el proceso de compilación y vinculación, los archivos .cpp se convierten a objetos puros o códigos de máquina que contienen referencias o símbolos indefinidos porque los archivos .h que se incluyen en su main.cpp aún no tienen implementación. Estos están listos para vincularse con otro archivo de objeto que define una implementación para su plantilla y, por lo tanto, tiene un ejecutable completo a.out.
Sin embargo, dado que las plantillas deben procesarse en el paso de compilación para generar código para cada instancia de plantilla que defina, por lo que simplemente compilar una plantilla separada de su archivo de encabezado no funcionará porque siempre van de la mano, por la misma razón que cada instancia de plantilla es una clase completamente nueva literalmente. En una clase regular, puede separar .h y .cpp porque .h es un modelo de esa clase y .cpp es la implementación en bruto, por lo que cualquier archivo de implementación se puede compilar y vincular regularmente, sin embargo, el uso de plantillas .h es un modelo de cómo la clase no debería verse como debería verse el objeto, lo que significa que un archivo de plantilla .cpp no es una implementación regular sin formato de una clase, es simplemente un plano para una clase, por lo que cualquier implementación de un archivo de plantilla .h puede '
Por lo tanto, las plantillas nunca se compilan por separado y solo se compilan donde sea que tenga una instanciación concreta en algún otro archivo fuente. Sin embargo, la instanciación concreta necesita conocer la implementación del archivo de plantilla, ya que simplemente modificando eltypename T
usar un tipo concreto en el archivo .h no va a hacer el trabajo porque lo que .cpp está allí para vincular, no puedo encontrarlo más adelante porque recordar plantillas son abstractas y no se pueden compilar, así que me veo obligado para dar la implementación en este momento, así sé qué compilar y vincular, y ahora que tengo la implementación, se vincula al archivo fuente adjunto. Básicamente, en el momento en que instancia una plantilla, necesito crear una clase completamente nueva, y no puedo hacer eso si no sé cómo debería ser esa clase cuando uso el tipo que proporciono a menos que notifique al compilador de la implementación de la plantilla, por lo que ahora el compilador puede reemplazarT
con mi tipo y crear una clase concreta que esté lista para ser compilada y vinculada.
En resumen, las plantillas son planos de cómo deberían verse las clases, las clases son planos de cómo debería verse un objeto. No puedo compilar plantillas separadas de su instanciación concreta porque el compilador solo compila tipos concretos, en otras palabras, plantillas al menos en C ++, es pura abstracción del lenguaje. Tenemos que restar plantillas, por así decirlo, y lo hacemos dándoles un tipo concreto con el que tratar para que nuestra abstracción de plantillas pueda transformarse en un archivo de clase regular y, a su vez, pueda compilarse normalmente. Separar el archivo de plantilla .h y el archivo de plantilla .cpp no tiene sentido. No tiene sentido porque la separación de .cpp y .h solo es donde el .cpp puede compilarse individualmente y vincularse individualmente, con plantillas, ya que no podemos compilarlas por separado, porque las plantillas son una abstracción,
Lo que significa typename T
que se reemplaza durante el paso de compilación, no el paso de vinculación, por lo que si trato de compilar una plantilla sin T
ser reemplazado como un tipo de valor concreto que no tiene ningún significado para el compilador y, como resultado, el código objeto no se puede crear porque no saber lo que T
es
Es técnicamente posible crear algún tipo de funcionalidad que guardará el archivo template.cpp y cambiará los tipos cuando los encuentre en otras fuentes, creo que el estándar tiene una palabra clave export
que le permitirá colocar plantillas en un archivo separado archivo cpp pero no muchos compiladores realmente implementan esto.
Solo una nota al margen, al hacer especializaciones para una clase de plantilla, puede separar el encabezado de la implementación porque una especialización, por definición, significa que me estoy especializando en un tipo concreto que se puede compilar y vincular individualmente.