template in error

E

eiji

Hi folks,

I have a linker - problem using a Matrix-template.
Maybe someone can help me with that.

Q:
"using femath::Matrix" or "using femath::Matrix<double>";

Consider this:

##########################
namespace femath {
....
template<class T> class Matrix
{
public:
Matrix();
Matrix(int rows);
Matrix(int rows, int columns);
virtual ~Matrix();
....
};
} //end namespace

namespace fesolv {

using femath::Matrix;

class AbstractSolver
{
public:
AbstractSolver(Model* model);
virtual ~AbstractSolver();

public:
virtual void Solve()=0;
....
protected:
Model* _model;
Matrix<double>* _systemstiffnessmatrix;
....
};

} //end namespace

##########################

Everything compiles great but the linker tells me:
AbstractSolver.obj : error LNK2019: unresolved external symbol "public:
__thiscall femath::Matrix<double>::Matrix<double>(int)"
(??0?$Matrix@N@femath@@QAE@H@Z) referenced in function "public:
__thiscall fesolv::AbstractSolver::AbstractSolver(class fesolv::Model
*)" (??0AbstractSolver@fesolv@@QAE@PAVModel@1@@Z)
......

I'm using VC++2005 and there is no external *.lib.
Matrix<class T> is in the same compile/link-unit.

Thanks a lot,
Sascha
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

eiji said:
Hi folks,

I have a linker - problem using a Matrix-template.
Maybe someone can help me with that.

Q:
"using femath::Matrix" or "using femath::Matrix<double>";

using femath::Matrix;
Consider this:

##########################
namespace femath {
...
template<class T> class Matrix
{
public:
Matrix();
Matrix(int rows);
Matrix(int rows, int columns);
virtual ~Matrix();
...
};
} //end namespace

namespace fesolv {

using femath::Matrix;

class AbstractSolver
{
public:
AbstractSolver(Model* model);
virtual ~AbstractSolver();

public:
virtual void Solve()=0;
...
protected:
Model* _model;
Matrix<double>* _systemstiffnessmatrix;
...
};

} //end namespace

##########################

Everything compiles great but the linker tells me:
AbstractSolver.obj : error LNK2019: unresolved external symbol "public:
__thiscall femath::Matrix<double>::Matrix<double>(int)"

The constructor
(??0?$Matrix@N@femath@@QAE@H@Z) referenced in function "public:
__thiscall fesolv::AbstractSolver::AbstractSolver(class fesolv::Model
*)" (??0AbstractSolver@fesolv@@QAE@PAVModel@1@@Z)

.... and it is called from the constructor of fesolv::AbstractSolver.

Regards, Stephan
 
E

eiji

That is clear. The constructor is called but not found. So why?
template<class T> Matrix<T>::Matrix(int)
{
...
}
exists!

Is there a "template<T>" phrase missing?
What can be the problem?
 
E

eiji

I tried this:

//main.cpp
namespace test {

template<class T> class Test
{
T i;
public:
Test(T t);

};

template<class T> Test<T>::Test(T t)
{
i = t;
}

}
int main(int argc , char *argv[])
{
using namespace test;
Test<int> T(1);
return 0;
}
#######

Compiles and links without problems!

but handling it this way:
#######
//a.h
namespace test {

template<class T> class Test
{
T i;
public:
Test(T t);

};
}
#####
//a.cpp
#include "a.h"
namespace test {

template<class T> Test<T>::Test(T t)
{
i = t;
}

}
//main.cpp
#include "a.h"
int main(int argc , char *argv[])
{
using namespace test;
Test<int> T(1);
return 0;
}

same error, the constructor is not found!
Any important linker-options?

Sorry, any suggestions?
Sascha
 
T

TB

eiji sade:
I tried this:
but handling it this way:
#######
//a.h
namespace test {

template<class T> class Test
{
T i;
public:
Test(T t);

};
}
#####
//a.cpp
#include "a.h"
namespace test {

template<class T> Test<T>::Test(T t)
{
i = t;
}

}
same error, the constructor is not found!
Any important linker-options?

Sorry, any suggestions?
Sascha

Compiler limitations. The template declarations and definitions must
be in the same translation unit.

Other solutions:
* Read about support for the 'export'-keyword for you compiler.
* #include the cpp-file after the declarations in the header-file.

TB
 
B

Ben Pope

eiji said:
Hi folks,

I have a linker - problem using a Matrix-template.
Maybe someone can help me with that.


class Model;

namespace femath {
template<class T> class Matrix
{
public:
Matrix();
Matrix(int rows);
Matrix(int rows, int columns);
virtual ~Matrix();
};
} //end namespace

namespace fesolv {

using femath::Matrix;

class AbstractSolver
{
public:
AbstractSolver(Model* model);
virtual ~AbstractSolver();

public:
virtual void Solve()=0;
protected:
Model* model_;
Matrix<double>* systemstiffnessmatrix_;
};
}

int main(int argc, char* argv[])
{
}

Works for me.

Ben Pope
 
E

eiji

TB said:
Compiler limitations. The template declarations and definitions must
be in the same translation unit.

Other solutions:
* Read about support for the 'export'-keyword for you compiler.
* #include the cpp-file after the declarations in the header-file.

TB

Most of the linker errors I have solved with that(declaration and
definition in the same translation unit). One more to go(link
operator). This is nearly the same problem.

Please Consider this:
#####################
namespace femath {

template<class T> class Matrix
{
public:
Matrix();
...
friend std::valarray<T> operator*(const Matrix& A, const
std::valarray<T>& b);
...
};
....
template<class T> std::valarray<T> operator*(const Matrix<T>& A, const
std::valarray<T>& b)
{
...
}
};

typedef std::valarray<double> DoubleVector;

void LinearSolver::ComputeSystemReactionVector()
{

Matrix<double>* tempStiffness = new Matrix<double>;
...
DoubleVector* uglob = new DoubleVector(0.0,dimension);
...
(*_reactionforce) = (*tempStiffness)*(*uglob);

delete uglob;
delete tempStiffness;
}
#####################
Error message:
LinearSolver.obj : error LNK2019: unresolved external symbol "class
std::valarray<double> __cdecl femath::eek:perator*(class
femath::Matrix<double> const &,class std::valarray<double> const &)"
(??Dfemath@@YA?AV?$valarray@N@std@@ABV?$Matrix@N@0@ABV12@@Z) referenced
in function "private: void __thiscall
fesolv::LinearSolver::ComputeSystemReactionVector(void)"
(?ComputeSystemReactionVector@LinearSolver@fesolv@@AAEXXZ)
#####################

The code works fine before translating Matrix into a template. The
operator works as expected.
Now the operator is not found during linkage. There must be one reason
why the definition is not accepted, but the declaration does.

Regards,
Sascha
 
B

Ben Pope

eiji said:
I tried this:

//main.cpp
namespace test {

template<class T> class Test
{
T i;
public:
Test(T t);

};

template<class T> Test<T>::Test(T t)
{
i = t;
}

}
int main(int argc , char *argv[])
{
using namespace test;
Test<int> T(1);
return 0;
}
#######

Compiles and links without problems!

but handling it this way:
#######
//a.h
namespace test {

template<class T> class Test
{
T i;
public:
Test(T t);

};
}
#####
//a.cpp
#include "a.h"
namespace test {

template<class T> Test<T>::Test(T t)
{
i = t;
}

}
//main.cpp
#include "a.h"
int main(int argc , char *argv[])
{
using namespace test;
Test<int> T(1);
return 0;
}

same error, the constructor is not found!
Any important linker-options?

Test is a template, so the compiler must be able to see the definition.

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12

Ben Pope
 
E

eiji

Test is a template, so the compiler must be able to see the definition.

Thanks Ben, great link!
################
//pre-declare each template friend function, add <> in the friend
lines
template<class T> class Matrix;
template<class T> std::valarray<T> operator* (const Matrix<T>& A, const
std::valarray<T>& b);
template<class T> Matrix<T> operator*(const Matrix<T>& A, const
Matrix<T>& B);

template<class T> class Matrix
{
public:
...
friend std::valarray<T> operator* <> (const Matrix& A, const
std::valarray<T>& b);
friend Matrix operator* <> (const Matrix& A, const Matrix& B);
...
};
################

Works fine!
Thank you all for a lesson on template-programming :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top