OVH Cloud OVH Cloud

Template : ou est l'erreur ?

8 réponses
Avatar
nico
Bonjour,

Je ne comprends pas pourquoi le code suivant ne compile pas (g++ rale car il
ne trouve soit disant pas Test<int>::Test() et Test<int>::~Test() au
linkage).


//main.cpp

#include "test.h"

//marche si j'inclu le test.cpp ici
//mais ca ne me parait pas tres élégant...


int main()
{
Test<int> t;

return 0;
}



//test.h

#ifndef TEST_H
#define TEST_H

template<class T> class Test
{

public:
Test();
~Test();

};

#endif





//test.cpp

#include "test.h"
#include <iostream>

template<class T>
Test<T>::Test()
{
T t;
std::cout << "Test()\n";
}

template<class T>
Test<T>::~Test()
{
std::cout << "~Test()\n";
}


Merci.

Nicolas.

8 réponses

Avatar
Nadine St-Amand
nico wrote:
Bonjour,

Je ne comprends pas pourquoi le code suivant ne compile pas (g++ rale car il
ne trouve soit disant pas Test<int>::Test() et Test<int>::~Test() au
linkage).


//main.cpp

#include "test.h"

//marche si j'inclu le test.cpp ici
//mais ca ne me parait pas tres élégant...


int main()
{


sans doute que ca marche quand test.cpp est compile avec le main dans le
meme fichier,

Peut-etre oublies-tu de compiler également le fichier test.cpp ?

Quelle est ta ligne de commande de compilation pour invoquer g++ ?

--
Nadine St-Amand

Avatar
Jean-Marc Bourguet
Essaie de trouver le message
avec google groups.
Si tu as du mal avec l'id (j'ai l'impression qu'il est
bizarre), quelques mots cles
"La norme definit deux modeles de compilation"
"modele d'inclusion".

Si tu lis l'anglais: http://www.bourguet.org/cpp/export.pdf

Maintenant, il y a au moins 2 compilateurs qui maintenant dipose de
export: como (qui est déjà cité dans ce message) et intel.

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++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
nico
Salut,

sans doute que ca marche quand test.cpp est compile avec le main dans le
meme fichier,

Peut-etre oublies-tu de compiler également le fichier test.cpp ?

Quelle est ta ligne de commande de compilation pour invoquer g++ ?



Non tout est bien compilé et linké, j'utilise le Makefilre suivant :

CXX=g++
CXXFLAGS=-pipe -Wall -W -O2 -fomit-frame-pointer -pipe -march=i586
-mtune=pentiumpro -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT

SRC= $(wildcard *.cpp)
OBJS= $(SRC:.cpp=.o)

EXE=3

$(EXE): $(OBJS)
@$(CXX) $^ -o $@ $(CXXFLAGS)

%.o: %.cpp
@$(CXX) -c $< $(CXXFLAGS)

main.o: main.cpp
mem.o: mem.cpp mem.h

clean:
@rm -f *.o *~ core *.core core.*




--
nico

Avatar
nico
Salut,


Essaie de trouver le message
avec google groups.
Si tu as du mal avec l'id (j'ai l'impression qu'il est
bizarre)
Non c'est bon ca marche avec l'id.


Si tu lis l'anglais: http://www.bourguet.org/cpp/export.pdf


Post & document interessants en tout cas, merci.

Ca me rappelle mes problème avec l'inline, c'était le même genre de choses,
il fallait se débrouiller pour inclure la source pour que ca marche...

Maintenant, il y a au moins 2 compilateurs qui maintenant dipose de
export: como (qui est déjà cité dans ce message) et intel.


Ok.

--
nico

Avatar
nico
Bonjour,

Oui, vous avez séparé l'implémentation du header. La solution est donnée
ici : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.7
Le problème avec cette solution c'est que l'on perd un peu l'effet template

puisque l'on doit prévoir les types utilisés (enfin je me comprend :))

C'est une sépcificité des templates qui est à prendre en compte.
Même si cela peut sembler étrange :

repeat after me, "I will do it anyway even though it's confusing." You
can trust me on this one.

En règle générale, mettez vos fonctions/méthodes génériques en dessous
de leur déclaration, et tout se passera bien.


C'est ce que ej vais finir par faire...

--
nico

Avatar
Alexandre
bonjour,

<snip sur pb classique des template dans cpp>

le problème c'est qu'une fonction "template" n'est pas vraiment une
fonction, mais un modèle. Ce qui veut dire : le compilateur ne peut pas
compiler ta fonction template sans connaitre le paramètre à utiliser...

template <class T> void f(const T& a)
{
// fonction inutile, certes
++a;
}

ce code n'est pas compilable tel quel (excepté avec des compilateurs
implémentant export, ce qui n'est le cas de presqu'aucun), et donc on doit
trouver une spécification dans la même unité de compilation (le même cpp
donc). En pratique, cela t'oblige à mettre le code des fonctions modèles
dans un .h (enfin un fichier d'en-tête tu l'appelles comme tu veux) à
inclure dans le .cpp (l'unité de compilation) qui va l'utiliser.
Avatar
nico
Bonjour,

ce code n'est pas compilable tel quel (excepté avec des compilateurs
implémentant export, ce qui n'est le cas de presqu'aucun), et donc on doit
trouver une spécification dans la même unité de compilation (le même cpp
donc). En pratique, cela t'oblige à mettre le code des fonctions modèles
dans un .h (enfin un fichier d'en-tête tu l'appelles comme tu veux) à
inclure dans le .cpp (l'unité de compilation) qui va l'utiliser.


OK merci pour la réponse, c'est ce que j'ai fais sous la forme

#ifndef TEST_H
#define TEST_H

template<class T> class Test
{
public:
Test();
~Test();

void f();
};


template<class T>
Test<T>::Test()
{
}

template<class T>
Test<T>::~Test()
{
}

template<class T>
Test<T>::f()
{
}


#endif

Pour quand même bien séparer déclaration/implémentation.

--
nico

Avatar
Alexandre
re-bonjour,

tu peux même faire :

Fichier Test.h
#ifndef TEST_H
#define TEST_H
template<class T> class Test
{
public:
Test();
~Test();

void f();
};
#endif

et fichier test.hpp (par exemple)

#include "test.h"
template<class T>
Test<T>::Test()
{
}

template<class T>
Test<T>::~Test()
{
}

template<class T>
Test<T>::f()
{
}

et dans ton .cpp où tu utilises le modèle :
#include "test.hpp"

Test<int > TestInt ;

si tu veux vraiment séparer complétement les 2.