[Linux] Compilation différentes?

Fermé
cl3ms - 26 oct. 2009 à 17:57
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 - 26 oct. 2009 à 18:59
Bonjour,

J'ai un petit souci sur un code avec classe & template

J'ai deux classes:


template <class T> class maillon {private:
T data ;
maillon<T> *suivant ;

public:
...
~maillon(){};
...

template <class U> friend class liste;
}

template <class T> class liste {
...
}

Mon souci n'est pas vraiment le code qui me semble bon. En effet chez deux amis, la compilation se passe sans souci et mon programme marche. Un est sous windows et compile via C::B, et l'autre est sous Ubuntu.

Je suis aussi sur Ubuntu mais ma compilation ne veut pas s'effectuer:

Client.o: In function `liste<char>::operator+(maillon<char> const&)':
Client.cc:(.text._ZN5listeIcEplERK7maillonIcE[liste<char>::operator+(maillon<char> const&)]+0xd2): undefined reference to `maillon<char>::~maillon()'

Je reçois ce message d'erreur pour plusieurs fonctions.


D'où celà peut-il venir? De mon code qui n'est pas assez portable? Ou de ma version d'Ubuntu? Ou d'un packet que je n'ai pas installé?
A voir également:

1 réponse

mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
26 oct. 2009 à 18:59
Ce qu'il faudrait faire idéalement

Bon déjà, il faut voir que à part pour le défi, ça n'a pas vraiment de sens de coder une liste template sachant que la STL fournit déjà un std::list<T> documenté par exemple ici :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583
https://forums.commentcamarche.net/forum/affich-37604421-introduction-a-la-stl-en-c-standard-template-library#std-list-t

Correction de ton code

Au niveau du code, malheureusement c'est un peu short et les template marchent sans problème avec g++. Il manque en outre des précisions sur les endroits ou tes classes templates sont implémentées et comment tu as compilé ton programme. Je vais donc essayer de répondre du mieux que je peux.

De manière générale, les templates doivent être implémentées dans le .hpp (sauf si l'usage de la classe template est restreint à un fichier .cpp, auquel cas on peut envisager de coder la classe dans ledit .cpp). Tu peux notamment jeter un oeil ici :
https://forums.commentcamarche.net/forum/affich-37604412-les-templates-en-c

Penchons-nous à présent sur ton code.

Comme ton destructeur est vide, tu n'as pas de raison de le déclarer/implémenter, tu peux le sous-entendre. A priori, si ton code est bien fait il ne devrait pas y avoir d'appel explicite au destructeur autrement que par un delete. Dans le cas d'une addition de maillon (je suppose que tu additionnes les données encapsulées dans le maillon ?), il n'y a pas spécialement de raison d'appeler le destructeur. Je me permets de postfixer ton type maillon avec un "_t" ce qui permettra d'écrire :

maillon_t maillon;


(... notation assez classique en C++ comme en témoignent les std::size_t ou les wchar_t). Pour revenir à ton opérateur (et si j'ai bien inféré son rôle) il doit ressembler à ceci :

template <typename T>
inline maillon_t operator+(
  const maillon_t & x,
  const maillon_t & y
){
  return maillon_t(x.get_data() + y.get_data());
}


... et il doit bien entendu être dans maillon.hpp en tant que fonction (opérateur) dépendant d'un paramètre template. On imagine bien sûr dans le code ci-dessus que ta classe maillon_t dipose d'un constructeur prenant en paramètre un const T & et d'un accesseur sur data :

#ifndef MAILLON_HPP
#define MAILLON_HPP

template <typename T>
class maillon_t
{
  protected:

    T data; // la donnée stockée dans le maillon

  public:

    // Le constructeur

    maillon_t(const T & data0):
      data(data0)
    {}

    // Accesseur sur data en lecture seule

    inline const T & get_data() const{
      return data;
    }

    //...
};

// L'opérateur + (qu'on aurait aussi pu implémenter directement dans la classe
// maillon_t en modifiant le prototype)

template <typename T>
inline maillon_t operator+(
  const maillon_t & x,
  const maillon_t & y
){
  return maillon_t(x.get_data() + y.get_data());
}

#endif


Pourquoi ton code ne compile pas

Il ne faut pas perdre de vue qu'un type template est un type qui dépend d'un paramètre et qui est compilé pour chaque combinaison de paramètre template. Ainsi si tu manipules un std::list<int> et un std::list<float>, tu compiles implicitement les deux types. C'est la raison pour laquelle une classe template réutilisable est intégralement dans le header (car on ne peut bien entendu pas compiler std::list<T> pour tous les types T imaginables !).

Dans ton cas il est probable que certaines fonctions de paramètres template soit implémentées dans un .cpp (ou dans un fichier compilé comme tel), et du coup, fatalement au moment de linker, certaines variantes templates ne sont pas trouvées. L'erreur survient au linkage car la déclaration colle avec ce qui était dans le header de la classe template. Toutefois comme je l'ai dis, si ta classe template est sensée être réutilisable dans plusieurs fichiers source (.cpp et .hpp), cette classe template DOIT être codée dans son .hpp.

Bonne chance
0