2010-03-30 5 views
5

Le code de modèle n'est pas compilé tant que la fonction modèle n'est pas utilisée. Mais où enregistre-t-il le code compilé, est-il sauvegardé dans le fichier objet à partir duquel la fonction template a été utilisée en premier lieu? Par exemple, main.cpp appelle une fonction de modèle à partir du fichier test.h, le compilateur génère un fichier objet main.o, La fonction de modèle est-elle dans le fichier main.o? parce que le code du template n'est pas en ligne, n'est-ce pas?Problème de compréhension des modèles dans C++

+0

Qu'est-ce qui vous fait penser que le code du modèle n'est pas inséré? Essayez de compiler un exemple simple avec l'optimisation activée et désassemblez le résultat. –

Répondre

4

Il dépend totalement de l'implémentation du compilateur. La plupart des compilateurs génèreront du code autour, en ligne ou dans des fichiers de type cpp, puis compileront avec cela. Parfois, avec une configuration d'optimisation, certains compilateurs réutilisent même le même code au lieu de le recréer pour chaque cpp.

Vous devez donc voir le document de votre compilateur pour plus de détails.

+3

C'est la bonne réponse, pas celle qui a été acceptée par le PO. –

0

Il est toujours en ligne (c'est-à-dire qu'il s'agit toujours d'un lien interne, ayant une sémantique en ligne). Il peut en fait ne pas être inline après tout, tout comme une fonction inline, cependant, le template n'est pas du code. C'est un "modèle pour faire du code". Par conséquent, il se trouvera normalement dans un en-tête, sauf cas particuliers, voir ci-dessous.

Il y avait une idée pour faire autre chose, le nom de code "export keyword". Il a été retiré de la norme.

Cas particuliers: vous pouvez compiler instanciations de modèle dans un fichier objet, sans les avoir utilisées. C'est le seul moyen d'éviter que tout le code du template ne soit inséré. Voici comment cela se fait:

template class std::vector<MyClass>; 

Cela forcera le compilateur à instancier un modèle dans l'emplacement actuel. C++ 0x aura une syntaxe pour forcer le compilateur pas de le faire, et ont la recherche d'éditeur de liens pour l'instanciation de modèle ailleurs:

extern template class std::vector<MyClass>; // C++0x only

+4

Ce n'est pas en ligne, nécessairement. Il est instancié dans l'unité de compilation et peut être en ligne mais peut ne pas l'être. –

+1

Le mot-clé export n'avait rien à voir avec inlining mais concernait plutôt la fourniture de modèles sous forme compilée pour une instanciation ultérieure par code client. –

0

Vous voulez dire instancié, non compilé. Au moment de la compilation, le compilateur découvre chaque version que votre code utilise et instaure (dans les fichiers objets) toutes les versions requises.

3

Oui, le code de fonction de modèle est émis dans le fichier main.o. Certains d'entre eux peuvent être en ligne, comme tout autre code peut être incorporé, mais en général, le code pour les modèles est émis dans n'importe quel fichier dans lequel le modèle est instancié. Pensez-y comme instanciant d'abord le code du template pour produire des fonctions normales non-template, puis compilant ces fonctions avec l'inline et l'optimisation que le compilateur applique à n'importe quelle autre fonction.

Lorsque le même instanciation de modèle (par exemple std::vector<int>) se produit dans plusieurs unités de compilation (.cpp fichiers), il y a un peu de difficulté, car le code est instancié dans chacun d'eux. Il existe plusieurs façons de gérer cela, impliquant parfois une étape de nettoyage dans la phase de liaison où les instanciations de modèles en double sont résolues en une seule; votre manuel du compilateur peut fournir plus d'informations sur la façon dont il gère cette situation.

+0

donc la création d'une classe de modèle avec une variable fictive qui n'est pas utilisée n'est pas la même chose que créer une classe et tout mettre dans le fichier d'en-tête. Le dernier sera en ligne et la classe du template dépend du compilateur? – hidayat

+0

@hidayat: Non. Les mêmes règles s'appliquent aux classes "normales" et aux modèles de classe. –

+0

Re doublons: Je pense que c'est une fonctionnalité standard des formats de fichiers objet d'avoir une section qui peut être combinée au moment de la liaison. Je * pense * qu'au moins un système les appelle sections 'COMDAT': http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWdev/LLM/p44.html (IIRC certains linkers vont même vérifier si les sections sont identiques pour attraper quelques erreurs.) – BCS

1

Le code de modèle est compilé même s'il n'est jamais instancié.Dans le cas contraire, les statisticiens ne peuvent pas être tenus d'émettre un diagnostic pour cela:

template< typename T > 
void f() 
{ 
    blah 
} 

compilation de modèle qui se passe dans deux phases. Outre les vérifications de base, tout ce qui dépend des paramètres de modèle ne peut être vérifié que lorsqu'un modèle est instancié et que les paramètres formels sont remplis avec des types réels. Par exemple, ici

template< typename T > 
void f() 
{ 
    typename T::nested_type x; 
} 

T::nested_type ne peut être vérifié après le modèle est instancié et un type réel est donnée pour T. Cependant, une vérification de base ("donné T::nested_type est un type, est-ce une définition de variable valide?") Est effectuée au moment où le compilateur rencontre la définition du modèle. (C'est pourquoi typename est requis, BTW.En fonction de T, T::nested_type pourrait tout aussi bien être le nom du membre de T ou un membre de données statiques - ce qui ferait une erreur de syntaxe T::nested_type x; Nous devons donc dire au compilateur de traiter T::nested_type comme le nom d'un type.)

Questions connexes