M
Micha
Hello there,
I think I've run into some classic c++ pitfall and maybe some of
you guys can help me out.
For my project I will need to use matrices and vectors and so I
decided to implement them by myself. I know there are already
tons of vector and matrix implementations, but I wanted to have
one taylored for my needs and without debugging someones
else code. Also is's become somewhat personal meanwhile ;-).
The plan :
- define a Matrix<T> and a Vector<T> class
- make them friends to perform some operations directly - quick
and dirty
- define the operators processing instances of more than one type
as friends
After a while and learning a lot about c++ syntax subtleness I made
the first two steps.
Now the linker (I'm using g++ 3.3.4 without any switches refering
templates) is nagging with complaints about not knowing the friend
operators I've defined.
Lets come to the details :
I've defined both classes separated into a header and the
implementation
and for all my template classes I'm using a single .cpp file which
includes
the class template implementations to explicitly instantiate the
specialized classes.
Both header files (matrix and vector) include each other. They contain
- the forward declarations of the class templates
- the operators prototypes
- the class template itself
- including the references to friend classes and friend operators
The operators are defined in the according class implementation files.
Some more details - I will show it exemplarily :
Vector.h
===================================================================
....
#include "Grid2D.h"
#include "Matrix.h"
namespace calcapp {
//a template method
template <class T> void doWhateveryouwant(const T& v);
//forward declaration of class template
template <class T> class Vector;
template <class T> class Matrix;
//operator prototypes
template <class T> Matrix<T> operator/ (const Vector<T>& v1, const
Vector<T>& v2);
....
//prototype of a test-method
template <class T> Vector<T> doNothing(const Vector<T>& v);
template <class T>
class Vector : public calcapp::Grid2D<T> {
public:
template <class TF> friend class Matrix;
Vector(int count_dim);
Vector(const Vector & other);
....
//tensor product
friend Matrix<T> operator/<T> (const Vector<T>& v1, const Vector<T>&
v2);
//dummy
friend Vector<T> doNothingInNS<T>(const Vector<T>& v);
protected:
....
}; //class
} //namespace
Vector.cpp
===================================================================
#include "Vector.h"
....
namespace calcapp {
template <class T>
Matrix<T> calcapp:perator/ (const Vector<T>& v1, const Vector<T>& v2)
{
Matrix<T> result(v1.size_x, v2.size_x);
....
return result;
} //tensorproduct
....
} //namespace
TemplateInstances.cpp
===================================================================
#include "global.h"
#include "Vector.cpp"
namespace calcapp {
template class Grid2D<fptype>;
template class Matrix<fptype>;
template class Matrix<int32>;
template class Matrix<int64>;
template class Vector<fptype>;
template class Vector<int32>;
template class Vector<int64>;
}
test.cpp
===================================================================
....
Vector<fptype) v1(3), v2(3);
....
....
===================================================================
So what the #!@* is wrong? That was obviously a linker error and for my
understanding the compiler didn't generate code for operator/<fptype>.
Correct?
--------------------------
The problem doesn't seem to be about operators because
....
v2 = calcapp::doNothing(v1);
....
would leed to an equivalent reaction.
--------------------------
And even
....
int i = 10;
doWhateveryouwant(i);
....
won't compile (link) :
So it seems it has nothing to do with classes or friends either.
But still somehow the linker figured out that the function was defined
in
the namespace calcapp.
--------------------------
Do I have to explicitly instantiate template methods too? I've
read nothing about that so far. How??
Operators?
Ok guys, what's the simple trick? ;-)
bye, Micha
I think I've run into some classic c++ pitfall and maybe some of
you guys can help me out.
For my project I will need to use matrices and vectors and so I
decided to implement them by myself. I know there are already
tons of vector and matrix implementations, but I wanted to have
one taylored for my needs and without debugging someones
else code. Also is's become somewhat personal meanwhile ;-).
The plan :
- define a Matrix<T> and a Vector<T> class
- make them friends to perform some operations directly - quick
and dirty
- define the operators processing instances of more than one type
as friends
After a while and learning a lot about c++ syntax subtleness I made
the first two steps.
Now the linker (I'm using g++ 3.3.4 without any switches refering
templates) is nagging with complaints about not knowing the friend
operators I've defined.
Lets come to the details :
I've defined both classes separated into a header and the
implementation
and for all my template classes I'm using a single .cpp file which
includes
the class template implementations to explicitly instantiate the
specialized classes.
Both header files (matrix and vector) include each other. They contain
- the forward declarations of the class templates
- the operators prototypes
- the class template itself
- including the references to friend classes and friend operators
The operators are defined in the according class implementation files.
Some more details - I will show it exemplarily :
Vector.h
===================================================================
....
#include "Grid2D.h"
#include "Matrix.h"
namespace calcapp {
//a template method
template <class T> void doWhateveryouwant(const T& v);
//forward declaration of class template
template <class T> class Vector;
template <class T> class Matrix;
//operator prototypes
template <class T> Matrix<T> operator/ (const Vector<T>& v1, const
Vector<T>& v2);
....
//prototype of a test-method
template <class T> Vector<T> doNothing(const Vector<T>& v);
template <class T>
class Vector : public calcapp::Grid2D<T> {
public:
template <class TF> friend class Matrix;
Vector(int count_dim);
Vector(const Vector & other);
....
//tensor product
friend Matrix<T> operator/<T> (const Vector<T>& v1, const Vector<T>&
v2);
//dummy
friend Vector<T> doNothingInNS<T>(const Vector<T>& v);
protected:
....
}; //class
} //namespace
Vector.cpp
===================================================================
#include "Vector.h"
....
namespace calcapp {
template <class T>
Matrix<T> calcapp:perator/ (const Vector<T>& v1, const Vector<T>& v2)
{
Matrix<T> result(v1.size_x, v2.size_x);
....
return result;
} //tensorproduct
....
} //namespace
TemplateInstances.cpp
===================================================================
#include "global.h"
#include "Vector.cpp"
namespace calcapp {
template class Grid2D<fptype>;
template class Matrix<fptype>;
template class Matrix<int32>;
template class Matrix<int64>;
template class Vector<fptype>;
template class Vector<int32>;
template class Vector<int64>;
}
test.cpp
===================================================================
....
Vector<fptype) v1(3), v2(3);
....
Matrix said:and here the compiler states :
../RunTest/test.cpp:310: undefined reference to `calcapp::Matrix<double> >calcapp:perator/<double>(calcapp::Vector<double> const&, calcapp::Vector<double> const&)'
....
===================================================================
So what the #!@* is wrong? That was obviously a linker error and for my
understanding the compiler didn't generate code for operator/<fptype>.
Correct?
--------------------------
The problem doesn't seem to be about operators because
....
v2 = calcapp::doNothing(v1);
....
would leed to an equivalent reaction.
--------------------------
And even
....
int i = 10;
doWhateveryouwant(i);
....
won't compile (link) :
undefined reference to `void calcapp::doWhateveryouwant<int>(int const&)'
So it seems it has nothing to do with classes or friends either.
But still somehow the linker figured out that the function was defined
in
the namespace calcapp.
--------------------------
Do I have to explicitly instantiate template methods too? I've
read nothing about that so far. How??
Operators?
Ok guys, what's the simple trick? ;-)
bye, Micha