Question

I'm writing some code which I want to publish as .h files and static library. The code is written using c++ template, with class declaration in .h file while definition in .cpp file. I used the "explicit instantiation" trick to make it possible to compile code into static library. The explicit instantiation is added at the end of .cpp file. I wrote some code to test this library. It works fine on macos and windows, but on ubuntu it returns the "undefined reference" linking error. It seems that the "explicit instantiation" trick doesn't work on ubuntu. Does anybody know why?

The version of g++ on ubuntu is 4.5.3.

Edit

This is the .h file of template class:

#ifndef PHYSIKA_CORE_MATRICES_MATRIX_2X2_H_
#define PHYSIKA_CORE_MATRICES_MATRIX_2X2_H_

#include "Physika_Core/Utilities/global_config.h"
#include "Physika_Core/Matrices/matrix_base.h"

namespace Physika{

template <typename Scalar>
class Matrix2x2: public MatrixBase<Scalar,2,2>
{
public:
Matrix2x2();
Matrix2x2(Scalar x00, Scalar x01, Scalar x10, Scalar x11);
~Matrix2x2();
inline int rows() const{return 2;}
inline int cols() const{return 2;}
Scalar& operator() (int i, int j);
const Scalar& operator() (int i, int j) const;
Matrix2x2<Scalar> operator+ (const Matrix2x2<Scalar> &) const;
//other operation declarations
//omitted here
};

//overriding << for Matrix2x2
template <typename Scalar>
std::ostream& operator<< (std::ostream &s, const Matrix2x2<Scalar> &mat)
{
  s<<mat(0,0)<<", "<<mat(0,1)<<std::endl;
  s<<mat(1,0)<<", "<<mat(1,1)<<std::endl;
  return s;
}

}  //end of namespace Physika

#endif //PHYSIKA_CORE_MATRICES_MATRIX_2X2_H_

The .cpp file of template class goes as:

#include "Physika_Core/Matrices/matrix_2x2.h"

namespace Physika{

template <typename Scalar>
Matrix2x2<Scalar>::Matrix2x2()
{
}

template <typename Scalar>
Matrix2x2<Scalar>::Matrix2x2(Scalar x00, Scalar x01, Scalar x10, Scalar x11)
{
#ifdef PHYSIKA_USE_EIGEN_MATRIX
  eigen_matrix_2x2_(0,0) = x00;
  eigen_matrix_2x2_(0,1) = x01;
  eigen_matrix_2x2_(1,0) = x10;
  eigen_matrix_2x2_(1,1) = x11;
#endif
}

//other operation definitions
//omitted here

//explicit instantiation of template so that it could be compiled into a lib
template class Matrix2x2<float>;
template class Matrix2x2<double>;

}  //end of namespace Physika

The test code is like:

#include <iostream>
#include "Physika_Core/Matrices/matrix_2x2.h"
using namespace std;
using Physika::Matrix2x2;

int main()
{
  cout<<"Matrix2x2 Test"<<endl;
  Matrix2x2<double> mat_double(2.0,1.0,1.0,2.0);
  cout<<"A 2x2 matrix of double numbers:"<<endl;
  cout<<mat_double;
  return 0;
}

The error information is:

g++ -Wall -Wno-write-strings -O2 -I ../../Public_Library/include -L ../../Public_Library/lib -l matrices matrix2x2_test.cpp -o matrix2x2_test
/tmp/ccUrtwwf.o: In function `main':
matrix2x2_test.cpp:(.text+0x91): undefined reference to `Physika::Matrix2x2<double>::Matrix2x2(double, double, double, double)'
matrix2x2_test.cpp:(.text+0x1b9): undefined reference to `Physika::Matrix2x2<double>::Matrix2x2(double, double, double, double)'
//more moitted here
collect2: ld returned 1 exit status
make: *** [matrix2x2_test] Error 1
Was it helpful?

Solution

I solved this problem by replacing the compile command

g++ -Wall -Wno-write-strings -O2 -I ../../Public_Library/include -L ../../Public_Library/lib -l matrices matrix2x2_test.cpp -o matrix2x2_test

with:

g++ matrix2x2_test.cpp -o matrix2x2_test -Wall -Wno-write-strings -O2 -I ../../Public_Library/include -L ../../Public_Library/lib -l matrices

It's so weird, what I did is just move "matrix2x2_test.cpp -o matrix2x2_test" ahead. Anyway, problem solved.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top