Bonjour, je suis un élève de BTS et nous travaillons actuellement sur un Tp qui concerne les type adaptatif (template).
Notre professeur nous à fourni un exemple de code à utilisé avec un template, rapidement il s'agit d'une pile qui empile et dépile des valeurs avec un type adaptatif justement.
Le souci est que lorsque nous essayons de répartir le programme avec le main, l'en-tête de la classe Pile et le code source de la classe Pile cela nous donne des erreurs comme :
undifined references to 'Pile<char>::Pile()'
Et pourtant le programme semble correct puisque qu'il fonctionne si l'ensemble du code fonctionne si il est mis dans un seul fichier main.
D'après mon professeur cela est normal et dû aux types adaptatifs en eux mêmes, il ne sait pas comment l'expliquer mais je suis malgré tout curieux de savoir pourquoi .
Si quelqu'un peut m'éclairer sur le sujet je suis preneur, j'en profite pour montrer le code et n'hésiter pas si vous voulez des précisions.
Oui, on ne peut pas séparer .hpp et .cpp pour les template. En effet le compilateur doit connaitre la définition complète de la fonction ou de la classe pour spécialiser. Le mieux est de mettre toute ta classe (déclaration et définition) dans un .hpp que tu peux inclure dans le main.
Si vraiment tu tiens à conserver la séparation déclaration/définition, tu peux simuler comme cela : déclarations dans un .hpp comme d'habitude, et définition dans un ".tpp" que tu inclues sous les déclarations de ton .hpp.
Pile.hpp
#ifndef PILE_H
#define PILE_H
#include <iostream>
using namespace std;
template<typename TYPE>
class Pile
{
public:
Pile();
TYPE depile();
void empile(TYPE);
private:
int sommet;
TYPE tab[100];
};
#include "Pile.tpp"
#endif
PS: Je laisse les autres maudire les tableaux à la C, les using namespace std, et l'enseignement en général du c++ dans le supérieur
Edit : Je complète un peu. Le but de la séparation .hpp et .cpp est de pouvoir compiler séparément des morceaux de code. C'est intéressant car si tu modifies une partie d'un gros projet, tu n'as pas à tout recompiler. Mais on ne peut pas compiler du code template séparément sans connaitre sa spécialisation. Car au final, les fonctions générées par le compilateur à partir d'un code template sont comme les fonctions ordinaires, le compilateur doit connaitre les types précis utilisés au moment de la compilation (à l'exécution tous les types sont nécessairement déterminés). Donc compiler du code template à part, sans les instanciations précises avec les types concrets utilisés est absolument impossible et n'a aucun sens. En conséquence, la séparation .cpp .hpp n'a pas de sens non plus, sauf pour des questions de présentation...
Je rajouterais qu' avec la loi de 'one definition rule' on ne peut pas instancier de fonction template en 2 ou plus d'exemplaire pour un même type donné, dans ce cas les fonctions templates sont inlinées dans les fonctions où elles sont appelées ( c'est à dire que le code de la fonction est copié tel quel dans la fonction appelante ).
Les fonctions templates ne sont pas inlinés, elles suivent les mêmes règles que le spécificateur inline et la règle de l'ODR s'applique de la même manière qu'une fonction non template: autoriser plusieurs définitions identiques au moment du link. Si toutes les définitions ne sont pas pareil, il va y avoir un problème, mais aucune vérification du compilateur. La stratégie de gcc et clang (et probablement les autres) est de prendre la première définition trouvée comme référence.
ODR => une définition par programme
ODR + inline => une définition par TU
Et pour préciser, utiliser inline ne fait pas en sorte que les fonctions soient inlinée, c'est juste un hint côté compilateur qui augmente la probabilité qu'elle le soit, ce n'est pas une obligation.
Si je comprends bien ton explication dans le cas de "ODR + inline > une définition par TU" , si il y a plusieurs fonctions identiques entre différentes translations units elles deviennent différentes dans leurs nom d'appel pour éviter de contredire la loi de ODR ?
Egalement:
"Si toutes les définitions ne sont pas pareilles, il va y avoir un problème" . Cela arrive si on utilise les concepts ? car il permettent d'adapter le corps de la fonction en fonction du(des) type(s) de la fonction template ?
> si il y a plusieurs fonctions identiques entre différentes translations units elles deviennent différentes dans leurs nom d'appel pour éviter de contredire la loi de ODR ?
Non, du tout, la fonction est dupliquée dans chaque TU et le linker n'en garde qu'une dans le programme final. C'est pour ça que s'il y a différentes implémentations entre TU, il va y avoir un problème puisqu'une seule sera utilisée.
Par exemple (je mets tout dans des .cpp parce que l'exemple est plus simple, mais c'est pareil en séparant dans des .h)
test1.cpp
inline int foo() { return 1; }
int g() { return foo(); }
test2.cpp
inline int foo() { return 2; }
int f() { return foo(); }
main.cpp
#include <iostream>
int f();
int g();
int foo();
int main()
{
std::cout << f() <<;
std::cout << g() <<;
std::cout << foo() <<;
}
Avec g++ test1.cpp test2.cpp main.cpp: 111
Avec g++ test2.cpp test1.cpp main.cpp: 222
Et le comportement va changer en fonction des flags utilisés et si le compilateur inline ou pas. Là, il ne fait pas d'inline parce que les optimisations ne sont pas activées. Avec cet exemple, si on ajoute -O1, il va y avoir une erreur de link parce qu'il ne trouve pas foo() dans main(). Mais si on vire l'appel de foo(), le résultat est alors 21.
Par contre, si on enlève inline, le linker se termine en erreur parce qu'il y a 2 implémentations de foo().
- Edité par jo_link_noir 18 janvier 2023 à 23:23:21
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Rien que ranger mon bureau me redonne 100 points de motivation
Rien que ranger mon bureau me redonne 100 points de motivation
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr