undefined reference to template function [duplicate]

I have three files . The contents of main.cpp are

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

When I try to compile these files with following command I get undefined reference error

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

Is there something wrong with the template declaration or implementation ? why M I getting these linking errors :?


The implementation of a non-specialized template must be visible to a translation unit that uses it.

The compiler must be able to see the implementation in order to generate code for all specializations in your code.

This can be achieved in two ways:

1) Move the implementation inside the header.

2) If you want to keep it separate, move it into a different header which you include in your original header:

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

You have 2 ways:

  1. Implement convert2QString in util.h.

  2. Manually instantiate convert2QString with int in util.cpp and define this specialization as extern function in 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); 
}