undefined reference to template function [duplicate]
Asked Answered
H

2

134

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 :?

Hornbeck answered 17/5, 2012 at 8:32 Comment(0)
S
212

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);
        }
}
Selfhood answered 17/5, 2012 at 8:32 Comment(2)
Many people use the .tcc extension for the template implementation files.Thoroughgoing
First time I hear .tccNaturally
B
45

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); 
}
Butterball answered 17/5, 2012 at 8:39 Comment(2)
extern template in .h file has errorPrewar
Yes, extern template QString convert2QString<int>(int type , int digits); would be correct, without the angle brackets.Putupon

© 2022 - 2024 — McMap. All rights reserved.