2012-05-17 12 views
55

Tengo tres archivos. El contenido de main.cpp sonreferencia indefinida a la función de plantilla

#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); 
     } 
} 

Cuando intento compilar estos archivos con comando siguiente me sale error de referencia indefinida

[email protected]:~/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 

Es Hay algo mal con la declaración o implementación de la plantilla? ¿Por qué tengo estos errores de enlace?

Respuesta

88

La implementación de una plantilla no especializada debe estar visible para una unidad de traducción que la use.

El compilador debe poder ver la implementación para generar código para todas las especializaciones en su código.

Esto se puede lograr de dos maneras:

1) mueven la implementación dentro de la cabecera.

2) Si desea mantenerlo separado, que se mueven en un encabezado distinto, que incluye en su cabecera 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); 
     } 
} 
+9

Mucha gente usa la extensión '.tcc' para la implementación de plantillas fi les. –

19

Tiene 2 formas:

  1. Implemento convert2QString in util.h.

  2. instancia manualmente con convert2QStringint en util.cpp y definir esta especialización como la función extern en 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); 
}