116 votes

référence indéfinie à une fonction de modèle

J'ai trois fichiers . Le contenu de main.cpp est

#include<iostream>
#include<QString>

#include "util.h"

int main()
{
    using Util::convert2QString;

    using namespace std;
    int n =22;
    QString tmp = convert2QString<int>(n);

    return 0;
}

util.h

namespace Util
{
    template<class T>
    QString convert2QString(T type , int digits=0);
}

util.cpp

namespace Util
{
    template<class T>
        QString convert2QString(T type, int digits=0)
        {
            using std::string;

            string temp = (boost::format("%1%") % type).str();

            return QString::fromStdString(temp);
        }
}

Lorsque j'essaie de compiler ces fichiers avec la commande suivante, je reçois une erreur de référence non définie.

vickey@tb:~/work/trash/template$ g++ main.cpp  util.cpp -lQtGui -lQtCore  -I. -I/usr/local/Trolltech/Qt-4.8.0/include/QtCore -I/usr/local/Trolltech/Qt-4.8.0/include/QtGui -I/usr/local/Trolltech/Qt-4.8.0/include
/tmp/cca9oU6Q.o: In function `main':
main.cpp:(.text+0x22): undefined reference to `QString Util::convert2QString<int>(int, int)'
collect2: ld returned 1 exit status

Y a-t-il un problème avec la déclaration ou l'implémentation du modèle ? Pourquoi ai-je ces erreurs de liaison : ?

184voto

Luchian Grigore Points 136646

L'implémentation d'un modèle non spécialisé doit être visible pour une unité de traduction qui l'utilise.

Le compilateur doit être capable de voir l'implémentation afin de générer du code pour toutes les spécialisations dans votre code.

Cela peut se faire de deux manières :

1) Déplacez l'implémentation à l'intérieur de l'en-tête.

2) Si vous voulez le garder séparé, déplacez-le dans un en-tête différent que vous incluez dans votre en-tête original :

util.h

namespace Util
{
    template<class T>
    QString convert2QString(T type , int digits=0);
}
#include "util_impl.h"

util_impl.h

namespace Util
{
    template<class T>
        QString convert2QString(T type, int digits=0)
        {
            using std::string;

            string temp = (boost::format("%1") % type).str();

            return QString::fromStdString(temp);
        }
}

41voto

inkooboo Points 1470

Vous avez deux possibilités :

  1. Mettre en œuvre convert2QString dans util.h.

  2. Instanciation manuelle convert2QString con int dans util.cpp et définir cette spécialisation comme fonction externe dans util.h

util.h

namespace Util
{
    template<class T>
    QString convert2QString(T type , int digits=0);

    extern template <> QString convert2QString<int>(int type , int digits);
}

util.cpp

 namespace Util {
     template<class T>
     QString convert2QString(T type, int digits)
     {
         using std::string;

         string temp = (boost::format("%1") % type).str();

         return QString::fromStdString(temp);
     }

     template <> QString convert2QString<int>(int type , int digits); 
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X