2010-11-25 6 views
1

J'ai une définition de classe de template qui doit être dans le fichier cpp. L'adoption de http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13, je l'ai fait quelque chose comme ceci:Problème de liaison de modèles C++

// File "foo.cpp" 
#include <iostream> 
#include "foo.h" 

template<typename T> void foo() 
{ 
    std::cout << "Here I am!\n"; 
} 

template void foo<int>(); 

J'instancier le modèle du fichier .cpp. Cependant, j'ai besoin de différents types comme foo (string) etc et j'ai réalisé que je ne pouvais l'instancier qu'une seule fois. Comment pourrais-je le réparer?

Merci.

+0

quel message d'erreur obtenez-vous si vous venez d'ajouter l'instruction 'template void foo ()'? – lijie

Répondre

4

Vous devriez être en mesure d'instancier foo pour chaque type dont vous avez besoin.

template void foo<int>(); 
template void foo<double>(); 
template void foo<std::string>(); 

C'est un peu onéreux, ce qui est la raison pour laquelle de nombreuses bibliothèques ont tendance à fournir des implémentations de fonction de modèle dans les fichiers d'en-tête, de sorte que toute instanciation peut être disponible à tout fichier cpp qui comprend l'en-tête.

+0

Je ne pense pas que c'est la raison pour laquelle les bibliothèques incluent des implémentations dans les fichiers d'en-tête. Si les bibliothèques connaissent les types avec lesquels vous allez instancier leurs modèles, il est possible de faire l'instanciation séparément. Cependant, la plupart des bibliothèques de modèles ne savent pas quels types seront utilisés pour les instancier, d'où la nécessité de fournir une implémentation dans les fichiers d'en-tête. – lijie

+0

Absolument. Même lorsque l'ensemble des types est quelque peu fixé, pour chaque nouveau type introduit, tous les fichiers d'implémentation pour les fonctions du modèle doivent être édités; cela viole certainement la localité du code. –

0

La spécialisation du modèle doit se faire dans une unité de traduction séparée (fichier .cpp) et la définition de modèle (générique) dans un fichier d'en-tête. Dans le foo.h ajouter la définition

template <typename T> void foo() 
{ 
    std::cout << "Here I am! << std::endl; 
} 

Dans le foo.cpp utiliser

foo <int>() 
foo <std::string>(); 
+1

Voulez-vous vraiment parler de spécialisation, pas d'instanciation? Si du code instancie un template et ne peut pas voir qu'il y a une spécialisation correspondante dans une autre unité de traduction, cela violerait l'ODR et conduirait probablement à des erreurs de linker ou à un comportement assez intéressant, non? –

+0

M'a pris une seconde (je l'aurais dit dans l'autre sens) mais Christopher Creutzig vous suggère de remplacer "spécialisation" par "instanciation", et il a raison. Spécialiser un modèle est de fournir un comportement spécial pour une combinaison particulière de types (comme pour le «vecteur » (malheureusement)). –