web-dev-qa-db-fra.com

référence non définie à la 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, j'obtiens 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 at-il quelque chose qui ne va pas avec la déclaration de modèle ou la mise en œuvre? Pourquoi M je obtenir ces erreurs de liaison:?

69
Vihaan Verma

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

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

Ceci peut être réalisé de deux manières:

1) Déplacez l'implémentation dans l'en-tête.

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

til.h

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

til_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);
        }
}
109
Luchian Grigore

Vous avez 2 façons:

  1. Mettre en place convert2QString in util.h.

  2. Instancier manuellement convert2QString avec int dans util.cpp et définir cette spécialisation en tant que 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); 
}
30
inkooboo