IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Template et "undefined reference to operator<<"


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut Template et "undefined reference to operator<<"
    Bonjour,
    J'ai un classe point
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <unsigned D> class PointT { ...
    friend ostream &operator<<(ostream &oS, const PointT<D> &P);
    ... }
    et une surcharge d'opérateur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <unsigned D>
    ostream &operator<<(ostream &oS, const PointT<D> &P)
    { ... }
    Dans mon main, j'ai
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       PointT<4> P4({1.15,3.6,1.8});
      cout << P4;
    Et j'obtiens l'erreur suivant sur "cout << P4":
    undefined reference to `operator<<(std::ostream&, PointT<4u> const&)'

    J'avoue que je cale sur le problème ... auriez-vous une idée ?
    En vous remerciant par avance.
    Christian

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Juste une petite question idiote : as-tu bien pensé à mettre le code du template dans l'header (.h) et non dans le fichier source (.cpp) ?

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    Oui - le fichier .h du template contient le header et le code (car c'est un bout de code de test que j'écrit). Le code de l'opérateur surchargé est avant mon main. En quoi cette séparation influe-t-elle ?

  4. #4
    Membre actif Avatar de Vespiras
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2012
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2012
    Messages : 168
    Points : 265
    Points
    265
    Par défaut
    Bonsoir, si tu veux dire que l'implémentation de ta surcharge d'opérateur est dans ton main, tant que ton main connait le header ou est placé le prototype, ça ne change rien. Après, pour plus de clarté et une organisation "typique", il vaut mieux séparer chaque .h et .cpp en fichiers distincts par classe.

    Pour ton problème, question toute bête : As-tu mis dans le header de la classe point un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <iostream>
    using namespace std;
    ?

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Vespiras Voir le message
    Bonsoir, si tu veux dire que l'implémentation de ta surcharge d'opérateur est dans ton main, tant que ton main connait le header ou est placé le prototype, ça ne change rien. Après, pour plus de clarté et une organisation "typique", il vaut mieux séparer chaque .h et .cpp en fichiers distincts par classe.
    On utilise ici une fonction template.
    Cf FAQ C++

    Citation Envoyé par Vespiras Voir le message
    Pour ton problème, question toute bête : As-tu mis dans le header de la classe point un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <iostream>
    using namespace std;
    ?
    En effet je pense qu'il l'a fait.
    Un autre lien de la FAQ s'impose.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut Merci Laurent !
    Je suis finalement arrivé à la conclusion (après quelques essais de fonctions friends sur des classes non templatées) que la solution (ou le problème) se trouvait dans la déclaration de fonction friends dans les classes templatées. Après une recherche sur Google, je suis arrivé sur ce lien http://www.developpez.net/forums/d22...plates-friend/ qui m'a guidé vers la solution. En déclarant la fonction comme ceci dans la classe template, ça marche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <unsigned Q> friend ostream &operator<<(ostream &oS, const PointT<Q> &P);
    (i.e. il faut rajouter devant ).
    Encore merci à vous, Laurent et le site developpez qui est vraiment une mine !
    Christian

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Certes, mais c'est vraiment plus laxiste.
    Est-ce ce que tu souhaites ?

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    En quoi est-ce plus laxiste ? Par ailleurs, je n'ai pas trouvé d'autre solution ... Bien sûr, je suis preneur d'alternatives :-)

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Citation Envoyé par coberle Voir le message
    En quoi est-ce plus laxiste ? Par ailleurs, je n'ai pas trouvé d'autre solution ... Bien sûr, je suis preneur d'alternatives :-)
    Tu va autoriser toutes les méthodes ostream &operator<<(ostream &oS, const PointT<Q> &P); à accéder au contenu de ta classe au lieu d'autoriser uniquement l'unique méthode utilisée pour afficher ta classe.

    Pourrais-tu nous montrer le fichier d'en-tête complet pour ta classe point ainsi que l'en-tête contenant ton opérateur << ?

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par coberle Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <unsigned D> class PointT { ...
    friend ostream &operator<<(ostream &oS, const PointT<D> &P);
    ... }
    Enlève ce que j'ai mis en gras.

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    En faisant comme tu le suggères, il y a 4 erreur qui sont générées, comme par exemple :
    invalid use of template-name 'PointT' without an argument list;
    ISO C++ forbids declaration of 'P' with no type [-fpermissive]

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    Neckara - voici le code de la classe PointT et du main. Encore merci pour ton aide (j'utilise CodeBlocks avec compil gnu/gcc)

    Classe PointT (PointT.h):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #ifndef POINTT_H_INCLUDED
    #define POINTT_H_INCLUDED
     
    #include <initializer_list>
     
    using namespace std;
     
    template <unsigned D> class PointT
    {
     public:
       PointT(initializer_list<float> coords);
       void Afficher();
     
       friend ostream &operator<<(ostream &oS, const PointT &P);
     
       static const unsigned dim;
     
     private:
        float m_coords[D]={0.0};
    };
     
    template <unsigned D>
    const unsigned PointT<D>::dim = D;
     
    template <unsigned D>
    PointT<D>::PointT(initializer_list<float> coords)
    {
        initializer_list<float>::iterator itr;
        int loop=min(D,coords.size());
        itr=coords.begin();
     
        for (int i=0; i<loop; i++)
            m_coords[i]=*itr++;
    }
     
    template <unsigned D>
    void PointT<D>::Afficher()
    {
       cout << "Dans afficher - " << this->m_coords[0] << endl;
    }
     
    #endif // POINTT_H_INCLUDED
    Main (main.cpp):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    #include <iostream>
    #include "PointT.h"
     
    using namespace std;
     
    template <unsigned D>
    ostream &operator<<(ostream &oS, const PointT<D> &P)
    {
        oS << "Point" << D << "D - (";
        for (int i=0; i<D-1; i++)
            oS << P.m_coords[i] << ",";
     
        oS << P.m_coords[D-1] << ")" << endl;
     
        return oS;
    }
     
    int main()
    {
        PointT<3> P({1.1,1.2,1.3});
     
        P.Afficher();
     
        cout << P; // ligne qui provoque l'erreur "undefined reference to "operator<< ..."
     
        return 0;
    }

  13. #13
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Pour régler ton problème de template :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template 
    <unsigned D> class PointT;
     
    template<unsigned D>
    ostream &operator<<(ostream &oS, const PointT<D> &P);
     
    //dans ta classe
    friend ostream &operator<<<>(ostream &oS, const PointT<D> &P);
    Attention, jamais de using namespace dans un header.

    Je continue de regarder les autres erreurs.

    EDIT : Dans ton constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int loop=min(D, (unsigned)coords.size());
    Résultat d'exécution :
    ~$ ./exe
    Dans afficher - 1.1
    Point3D - (1.1,1.2,1.3)
    Est-ce bien le résultat attendu ?

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    Merci Neckara ... ça fonctionne.
    Mais je ne suis pas certain de bien comprendre le pourquoi du comment:
    - pourquoi ceci avant la classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template 
    <unsigned D> class PointT;
     
    template<unsigned D>
    ostream &operator<<(ostream &oS, const PointT<D> &P);
    - pourquoi ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend operator<<<> ...
    PS - je crois qu'il y a une réponse ici http://stackoverflow.com/questions/4...lass-templates

  15. #15
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par coberle Voir le message
    Merci Neckara ... ça fonctionne.
    Mais je ne suis pas certain de bien comprendre le pourquoi du comment:
    - pourquoi ceci avant la classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template 
    <unsigned D> class PointT;
     
    template<unsigned D>
    ostream &operator<<(ostream &oS, const PointT<D> &P);
    C'est le principe des déclarations anticipées.

    Citation Envoyé par coberle Voir le message
    - pourquoi ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend operator<<<> ...
    PS - je crois qu'il y a une réponse ici http://stackoverflow.com/questions/4...lass-templates
    En fait tu dis que ta classe est friend avec une spécialisation de ta méthode template.
    Si j'ai mis les <> c'est surtout parce que le warning me demandait de les mettre.
    Mais d'après ton lien, c'est juste pour informer que la fonction est template.


    Sinon ton code est correct si tu souhaites que seul main.cpp puisse utiliser la fonction template sinon, cf FAQ.

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    Merci beaucoup, c'est vraiment sympa.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 20/03/2011, 02h21
  2. System - Event / Template => undefined reference
    Par Whyzix dans le forum Langage
    Réponses: 8
    Dernier message: 06/04/2010, 23h18
  3. " undefined reference to " avec methode template
    Par coldrink dans le forum Langage
    Réponses: 3
    Dernier message: 24/10/2009, 20h05
  4. Réponses: 6
    Dernier message: 18/03/2009, 12h27
  5. [Template] Templates et undefined reference
    Par FadeOut dans le forum C++
    Réponses: 9
    Dernier message: 12/12/2008, 17h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo