Classe Template
Le
sej
Bonjour,
J'ai une classe template et j'ai une erreur au linkage.
Si je déclare le contructeur de la classe Test en inline ou dans le
fichier main.cpp ça passe sinon j'ai l'erreur suivante sous Visual .Net
2003 :
Compilation
main.cpp
Édition des liens en cours
main.obj : error LNK2019: symbole externe non résolu "public: __thiscall
Test<char>::Test<char>(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,char)"
(??0?$Test@D@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@D@Z)
référencé dans la fonction _main
main.obj : error LNK2019: symbole externe non résolu "public: __thiscall
Test<int>::Test<int>(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,int)"
(??0?$Test@H@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)
référencé dans la fonction _main
Debug/template.exe : fatal error LNK1120: 2 externes non résolus
--
// Template.h
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Test
{
public:
Test (string name, T val);// {_val = val; cout <<
"construct name=" << name << ", _val=" << _val << endl;};
T GetVal (void) {return _val; };
void SetVal (T val) {_val = val; };
int Size (void) {return sizeof(_val); };
private:
T _val;
};
#endif
--
// Template.cpp
// template.cpp : définit le point d'entrée pour l'application console.
//
#include <iostream>
#include <string>
#include "template.h"
using namespace std;
template<class T>
Test<T>::Test(string name, T val)
{
_val = val; cout << "construct name=" << name << ", _val=" << _val
<< endl;
}
// Main.cpp
// template.cpp : définit le point d'entrée pour l'application console.
//
#include <iostream>
#include <string>
#include "template.h"
using namespace std;
int main(int argc, char **)
{
Test<int> t("toto", 9);
t.SetVal(5);
cout << t.GetVal() << endl;
cout << t.Size() << endl;
Test<char> c("test", 'Z');
c.SetVal('0');
cout << c.GetVal() << endl;
cout << c.Size() << endl;
return 0;
}
J'ai une classe template et j'ai une erreur au linkage.
Si je déclare le contructeur de la classe Test en inline ou dans le
fichier main.cpp ça passe sinon j'ai l'erreur suivante sous Visual .Net
2003 :
Compilation
main.cpp
Édition des liens en cours
main.obj : error LNK2019: symbole externe non résolu "public: __thiscall
Test<char>::Test<char>(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,char)"
(??0?$Test@D@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@D@Z)
référencé dans la fonction _main
main.obj : error LNK2019: symbole externe non résolu "public: __thiscall
Test<int>::Test<int>(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,int)"
(??0?$Test@H@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z)
référencé dans la fonction _main
Debug/template.exe : fatal error LNK1120: 2 externes non résolus
--
// Template.h
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Test
{
public:
Test (string name, T val);// {_val = val; cout <<
"construct name=" << name << ", _val=" << _val << endl;};
T GetVal (void) {return _val; };
void SetVal (T val) {_val = val; };
int Size (void) {return sizeof(_val); };
private:
T _val;
};
#endif
--
// Template.cpp
// template.cpp : définit le point d'entrée pour l'application console.
//
#include <iostream>
#include <string>
#include "template.h"
using namespace std;
template<class T>
Test<T>::Test(string name, T val)
{
_val = val; cout << "construct name=" << name << ", _val=" << _val
<< endl;
}
// Main.cpp
// template.cpp : définit le point d'entrée pour l'application console.
//
#include <iostream>
#include <string>
#include "template.h"
using namespace std;
int main(int argc, char **)
{
Test<int> t("toto", 9);
t.SetVal(5);
cout << t.GetVal() << endl;
cout << t.Size() << endl;
Test<char> c("test", 'Z');
c.SetVal('0');
cout << c.GetVal() << endl;
cout << c.Size() << endl;
return 0;
}

Poser une question


memebres dans le .h en dessous de la définition de la classe.
La question est donc : est-ce que le compilo sait linker une classe
template compilée, si une classe template est compilable ? ou est-ce que
le compilo interprète le .h pour générer les classes ?
Gaby, je crois que c'est un bon candidat pour la FAQ...
La norme définit deux modèles de compilation. Ces deux
modèles partagent certaines choses -- dont la recherche des
noms en deux phases -- et diffèrent principalement sur la
manière dont la définition d'un template est trouvée
lorsqu'une instantiation est nécessaire.
* le modèle d'inclusion où dès qu'un template est
instantié dans une unité de compilation il faut que la
déclaration y soit aussi présente. Ce modèle est
supporté par la totalité des compilateurs (qui
généralement ne diagnostiquent pas le fait que la
déclaration est absente et se contentent alors de ne pas
générer les instantiations).
* le modèle de compilation séparée où la déclaration doit
etre marquée avec "export" (pas explicitement d'après la
norme mais je crois qu'il y a un DR sur le sujet et
c'est bien nécessaire pour les implémentations
disponibles) et la définition doit être fournie dans une
seule unite de compilation. À ma connaissance, une
seule implémentation est disponible, celle d'EDG qui est
disponible à travers les compilateurs de Comeau et
d'Intel.
Les deux compilateurs disposant du modèle de compilation
séparée pour les templates ont besoin que les définitions
soient disponibles au moment de l'édition de lien et génèrent
le code à ce moment-là si c'est nécessaire. Ils pouraient les
compiler en quelque chose ressemblant aux en-têtes
pré-compilés mais ce n'est pas quelque chose de disponible.
Faire des templates avec du code partagé n'est vraiment pas
pratique en C++ (par exemple si on a
template <typename T> void f();
f<int> et f<long> doivent avoir des adresses différentes)
Ça marche avec tout les compilateurs.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
J'ai regardé sur la MSDN et l' "export" n'est pas géré par le
compilateur de Visual .Net donc je reste sur la solution des définitions
dans le .h
http://msdn.microsoft.com/library/d...mplate.asp:
The export keyword is not supported on templates. For example, the
following sample will not compile:
export template <class T> void fun(T);
export template <class T> class A;
Apres une relecture rapide de l'ODR, je ne sais pas si la norme le
demande ou pas et je n'ai pas le temps de regarder ca plus en
profondeur. En fait je ne suis meme pas sur qu'EDG le verifie. Je
verrai ca chez moi si j'ai le temps. J'avais simplement extrapole --
peut-etre un peu vite -- l'ODR des fonctions aux templates exportes.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org