[Template] Templates et undefined reference
Bonjour à tous,
j'ai un petit problème ici avec les templates....
il semble qu'une référence n'est pas bonne... voici mon code....
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#include <iostream>
#include <stdexcept>
#include <fstream>
#include "Trie.hpp";
using namespace std;
void checkArgs(int argc, char *argv[], ifstream & ficIn, ofstream & ficOut);
int main(int argc, char *argv[]) {
ifstream fichierIn;
ofstream fichierOut;
int test2;
try {
//checkArgs(argc, argv, fichierIn, fichierOut);
Trie <int>test(3);
test.ajouteElement((string)"abc",&test2);
fichierIn.close();
fichierOut.close();
}
catch (runtime_error erreur) {
cerr << erreur.what();
return -1;
}
return 0;
} |
le problème est à la ligne Trie<int> test(3);
voici le contenu de la classe Trie
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
#include "Trie.hpp"
using namespace std;
bool checkCle(string cle, int nblettres);
template<typename T>
Trie<T>::Trie(unsigned nblettres) throw(runtime_error) {
if (nblettres > NBLETTRESMAX)
throw runtime_error("Trie() : nombre de lettres hors-bornes!");
nbLettres = nblettres;
}
template<typename T>
bool Trie<T>::ajouteElement(string uneCle, T* unElement) throw(runtime_error) {
Trie<T> uneTrie;
if (unElement == NULL)
throw runtime_error ("ajouteElement() : Insertion d'élement 'null'");
if (!checkCle(uneCle, nbLettres))
throw runtime_error ("ajouteElement() : Cle invalide.");
if (enfants[tolower(uneCle[0])-42] == NULL) {
enfants[tolower(uneCle[0])-42] = new Trie<T>(nbLettres);
}
if (uneCle.length() == 1)
element = unElement;
else
enfants[tolower(uneCle[0])-42].ajouteElement(uneCle.substr(1,uneCle.length()-1));
}
bool checkCle(string cle, int nblettres)
{
int i=0;
bool isOk = true;
while (i<cle.length() && isOk != false) {
isOk = (tolower(cle[i]) >= LETTREMIN && tolower(cle[i]) < (LETTREMIN + nblettres));
i++;
}
return isOk;
} |
finalement son header:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
template <typename T> class Trie {
friend class IteratorPrefixe;
public:
// Cree un trie basé sur un alphabet de nblettres, ou nblettres doit avoir une valeur comprise
// entre 1 et NBLETTRESMAX inclusivement
Trie(unsigned nblettres) throw(runtime_error);
// Ajoute un élément dont la clé est donnée en premier argument et le contenu en second argument
// Le contenu doit être défini (pointeur différent de NULL)
// La clé doit être composée de lettres valides (soit les lettres comprises entre a inclusivement et a+nblettres exclusivement
// par exemple : si nblettres vaut 3, a, b et c sont les seuls caractères autorisés;
// si nblettres vaut 15, seules les lettres entre a et o inclusivement sont autorisées.
// Renvoie true si l'insertion a pu se faire, renvoie false sinon.
bool ajouteElement(string, T*) throw(runtime_error);
// Supprime un élément dont la clé est donnée en argument et renvoie le contenu du noeud supprimé
// La clé doit être composée de lettres valides (voir ci-dessus)
// Peut egalement supprimer en meme temps des ancetres du noeud mentionne, si ces ancetres sont devenus inutiles
// Renvoie NULL si l'élément a supprimer n'existe pas
T* supprimeElement(string cle) throw(runtime_error);
// Cherche un élément dont la clé est donnée en argument et renvoie le contenu associé
// La clé doit être composée de lettres valides (voir ci-dessus)
// Renvoie NULL si la clé n'existe pas
T* chercheElement(string cle) throw();
// Classe d'itérateur permettant de parcourir le trie en profondeur en mode préfixe
class IteratorPrefixe;
// Renvoie un itérateur pointant sur le premier élément du parcours du trie en profondeur en mode préfixe
IteratorPrefixe pbegin() throw(runtime_error);
// Renvoie un itérateur pointant au-delà du dernier élément du parcours du trie en profondeur en mode préfixe
IteratorPrefixe pend() throw();
private:
unsigned nbLettres;
T* element;
vector<Trie<T> *> enfants;
Trie<T> * parent;
// Cette fonction supprime un noeud et ses ancêtres devenus inutiles. Elle fait essentiellement le meme travail
// que supprimeElement : c'est la façon de désigner le noeud a supprimer qui change. De plus, contrairement a
// supprimeElement, elle ne retourne aucune information sur le noeud supprimé.
void supprime(Trie<T> * noeud) throw();
// Cette fonction cherche un noeud en fonction d'une clé donnée. Elle fait essentiellement le meme travail
// que chercheElement mais renvoie une référence au noeud trouvé (ou NULL si le noeud n'existe pas)
// La clé doit être composée de lettres valides (voir ci-dessus)
Trie<T>* cherche(string cle) throw(runtime_error);
};
template <typename T> class Trie<T>::IteratorPrefixe{
friend class Trie<T>;
public:
IteratorPrefixe() : arbre(NULL), noeudCourant(NULL), cleCourante("") {};
pair<string, T*> operator*() {return make_pair(cleCourante, noeudCourant -> element);} ;
IteratorPrefixe operator++()throw(runtime_error);
void operator=(IteratorPrefixe iter) {arbre = iter.arbre; noeudCourant = iter.noeudCourant; cleCourante = iter.cleCourante;};
bool operator==(IteratorPrefixe iter) {return arbre == iter.arbre && noeudCourant == iter.noeudCourant;};
bool operator!=(IteratorPrefixe iter) {return arbre != iter.arbre || noeudCourant != iter.noeudCourant;};
private:
Trie<T> * arbre;
Trie<T> * noeudCourant;
string cleCourante;
}; |
quelqu'un a une petite idée?
Je ne peux modifier en aucun cas mon Hpp
Comme j'ai dit un peu plus haut,
il faut absolument que le .hpp reste intact, car lors de la correction du TP, il sera remplacé par sa version originale.....
il faut donc trouvé une solution différente.... malheureusement.....
j'ai essayé d'autres choses par contre... sauf que maintenant, j'ai de nouvelles erreurs....
au lieu de faire :
#include "Trie.hpp" dans main.cpp
je fais #include "Trie.cpp"
mais par la suite, j'Ai une erreur totalement différentes....
ça me donnne
multiple definition of 'checkCle(std::string, int)'