Le compilateur génère du code pour chaque instanciation de modèle lorsque vous utilisez un modèle lors de l'étape de compilation. Dans le processus de compilation et de liaison, les fichiers .cpp sont convertis en objet pur ou en code machine qui contient en eux des références ou des symboles non définis car les fichiers .h qui sont inclus dans votre main.cpp n'ont ENCORE aucune implémentation. Ceux-ci sont prêts à être liés à un autre fichier objet qui définit une implémentation de votre modèle et vous disposez donc d'un exécutable a.out complet.
Cependant, étant donné que les modèles doivent être traités lors de l'étape de compilation afin de générer du code pour chaque instanciation de modèle que vous définissez, la simple compilation d'un modèle distinct de son fichier d'en-tête ne fonctionnera pas car ils vont toujours de pair, pour la raison même que chaque instanciation de modèle est littéralement une toute nouvelle classe. Dans une classe régulière, vous pouvez séparer .h et .cpp car .h est un plan directeur de cette classe et le .cpp est l'implémentation brute, de sorte que tous les fichiers d'implémentation peuvent être compilés et liés régulièrement, cependant l'utilisation de modèles .h est un plan directeur de la façon la classe ne doit pas ressembler à l'objet, ce qui signifie qu'un fichier modèle .cpp n'est pas une implémentation régulière brute d'une classe, c'est simplement un plan pour une classe, donc toute implémentation d'un fichier modèle .h peut '
Par conséquent, les modèles ne sont jamais compilés séparément et ne sont compilés que lorsque vous avez une instanciation concrète dans un autre fichier source. Cependant, l'instanciation concrète doit connaître l'implémentation du fichier modèle, car il suffit de modifier letypename T
l'utilisation d'un type concret dans le fichier .h ne fera pas le travail car ce que .cpp est là pour lier, je ne le trouverai pas plus tard car les modèles de rappel sont abstraits et ne peuvent pas être compilés, donc je suis forcé pour donner l'implémentation maintenant, donc je sais quoi compiler et lier, et maintenant que j'ai l'implémentation, elle est liée dans le fichier source inclus. Fondamentalement, au moment où j'instancie un modèle, j'ai besoin de créer une toute nouvelle classe, et je ne peux pas le faire si je ne sais pas à quoi devrait ressembler cette classe lorsque j'utilise le type que je fournis, sauf si je le fais remarquer au compilateur de l'implémentation du modèle, maintenant le compilateur peut remplacer T
par mon type et créer une classe concrète prête à être compilée et liée.
Pour résumer, les modèles sont des plans directeurs pour l'apparence des classes, les classes sont des plans directeurs pour l'apparence d'un objet. Je ne peux pas compiler de modèles séparés de leur instanciation concrète car le compilateur ne compile que des types concrets, en d'autres termes, les modèles au moins en C ++, sont une pure abstraction de langage. Nous devons pour ainsi dire résilier les modèles, et nous le faisons en leur donnant un type concret à traiter afin que notre abstraction de modèle puisse se transformer en un fichier de classe ordinaire et à son tour, il peut être compilé normalement. La séparation du fichier .h de modèle et du fichier .cpp de modèle n'a aucun sens. C'est absurde parce que la séparation de .cpp et .h n'est que là où le .cpp peut être compilé individuellement et lié individuellement, avec des modèles car nous ne pouvons pas les compiler séparément, car les modèles sont une abstraction,
Le sens typename T
est remplacé pendant l'étape de compilation et non pas l'étape de liaison, donc si j'essaie de compiler un modèle sans T
être remplacé comme un type de valeur concret qui n'a absolument aucun sens pour le compilateur et comme résultat, le code objet ne peut pas être créé car il ne le fait pas savoir ce qui T
est.
Il est techniquement possible de créer une sorte de fonctionnalité qui sauvera le fichier template.cpp et changera les types quand il les trouvera dans d'autres sources, je pense que la norme a un mot export
- clé qui vous permettra de mettre des modèles dans un autre fichier cpp mais pas que de nombreux compilateurs implémentent réellement cela.
Juste une note latérale, lorsque vous faites des spécialisations pour une classe de modèle, vous pouvez séparer l'en-tête de l'implémentation car une spécialisation par définition signifie que je me spécialise pour un type concret qui peut être compilé et lié individuellement.