Hi people,
i'm using a templated class on my dll and it compiles and link fine, but I find that it has introduced some symbols of my templated class on the dll. It also happens with any program that includes that templated class so I have linking errors on programs that use this library because of the redefined symbols.

linking problems with templates
parmanu
Here is the templated class, all is done on the header.
template <int N>
class gfxDimensionalUnit
{
public:
gfxDimensionalUnit()
: m_Initialized(false)
{
}
gfxDimensionalUnit(const gfxDimensionalUnit<N> &right)
: m_Initialized(false)
{
m_Initialized = right.m_Initialized;
memcpy(m_data,right.m_data,N*sizeof(double));
}
// Constructor from a vector of doubles with size elements
gfxDimensionalUnit(const double* coord, unsigned int size)
: m_Initialized(false)
{
if(size != N)
return;
memcpy(m_data,coord,N*sizeof(double));
m_Initialized = true;
return;
}
const gfxDimensionalUnit<N> & operator=(const gfxDimensionalUnit<N> &right)
{
m_Initialized = right.m_Initialized;
memcpy(m_data,right.m_data,N*sizeof(double));
return *this;
}
bool operator==(const gfxDimensionalUnit<N> &right) const
{
if(right.IsNull()) return false;
for(int i = 0; i < N; i++)
if(fabs(m_data
return true;
}
bool operator!=(const gfxDimensionalUnit<N> &right) const
{
return !(*this == right);
}
// Set all N components.
// The object is marked as initialized.
virtual void SetComponents(double* coord, unsigned int size)
{
if(size == N)
{
memcpy(m_data,coord,N*sizeof(double));
m_Initialized = true;
}
else
m_Initialized = false;
}
// Get all three components. Return true if the object has
// been initialized.
virtual bool GetComponents(double* coord, unsigned int size)
{
if(size == N)
{
memcpy(coord,m_data,N*sizeof(double));
return m_Initialized;
}
else
return false;
}
// returns if the object hasn't been yet initialized
virtual bool IsNull() const
{
return !m_Initialized;
}
// Access to one component for both read and write
// operations.
// Warning: if the vector is null, setting one component to
// a new value will not set the "Initialized" variable.
double& operator ()(int indx)
{
return m_data[indx];
}
// Access to one component for read-only operations.
const double& operator ()(int indx) const
{
return m_data[indx];
}
// Access to one component for both read and write
// operations.
// Warning: if the vector is null, setting one component to
// a new value will not set the "Initialized" variable.
double& operator [](int indx)
{
return m_data[indx];
}
// Access to one component for read-only operations.
const double& operator [](int indx) const
{
return m_data[indx];
}
// Get a constant pointer to the data.
operator const double*() const
{
return m_data;
}
// Add another vector.
friend gfxDimensionalUnit<N> operator +(const gfxDimensionalUnit<N>& vec1, const gfxDimensionalUnit<N>& vec2)
{
if(vec1.IsNull() || vec2.IsNull()) return gfxDimensionalUnit<N>();
gfxDimensionalUnit<N> res(vec1);
for(int i = 0; i < N; i++)
res
return res;
}
// Substract another vector.
friend gfxDimensionalUnit<N> operator -(const gfxDimensionalUnit<N>& vec1, const gfxDimensionalUnit<N>& vec2)
{
if(vec1.IsNull() || vec2.IsNull()) return gfxDimensionalUnit<N>();
gfxDimensionalUnit<N> res(vec1);
for(int i = 0; i < N; i++)
res
return res;
}
// increment actual vector with another vector
virtual const gfxDimensionalUnit<N>& operator +=(const gfxDimensionalUnit<N>& vect)
{
//As we assign, if we add a Null vector the current vector gets also Null
if(!vect.IsNull() && !IsNull())
for(int i = 0; i < N; i++)
m_data
else
m_Initialized = false;
return *this;
}
// decrements actual vector with another vector
virtual const gfxDimensionalUnit<N>& operator -=(const gfxDimensionalUnit<N>& vect)
{
if(!vect.IsNull() && !IsNull())
for(int i = 0; i < N; i++)
m_data
else
m_Initialized = false;
return *this;
}
// Scales the vector with the factor val
virtual const gfxDimensionalUnit<N>& operator *=(double val)
{
if(!IsNull())
for(int i = 0; i < N; i++)
m_data
return *this;
}
// Scales the vector by a factor 1/val
virtual const gfxDimensionalUnit<N>& operator /=(double val)
{
if(!IsNull() && val > GFX_ZERO_TOLERANCE)
for(int i = 0; i < N; i++)
m_data
return *this;
}
// returns the vector scaled by a value 1/val
friend gfxDimensionalUnit<N> operator /(const gfxDimensionalUnit<N>& vec, double val)
{
if(!vec.IsNull() && val > GFX_ZERO_TOLERANCE)
{
gfxDimensionalUnit<N> res(vec);
return res /= val;
}
else
return gfxDimensionalUnit<N>();
}
// returns the vector scaled by a value val
friend gfxDimensionalUnit<N> operator *(const gfxDimensionalUnit<N>& vec, double val)
{
if(!vec.IsNull())
{
gfxDimensionalUnit<N> res(vec);
return res *= val;
}
else
return gfxDimensionalUnit<N>();
}
// returns the vector scaled by a value val
friend gfxDimensionalUnit<N> operator *(double val, const gfxDimensionalUnit<N>& vec)
{
return vec * val;
}
// writes the N components in the ostream
friend std::ostream & operator <<(std::ostream& os, const gfxDimensionalUnit<N>& vec)
{
char buffer[80];
for(int i = 0; i < N; i++)
{
sprintf_s(buffer,"%.3f ",vec
os << buffer;
}
os << std::endl;
return os;
}
// reads the N elements from the istream
friend std::istream& operator >>(std::istream& is, gfxDimensionalUnit<N>& vec)
{
for(int i = 0; i < N; i++)
is >> vec
vec.m_Initialized = true;
return is;
}
virtual gfxType GetType() const
{
return GFX_DIMENSIONAL_UNIT;
}
protected:
// Flag that is true when the vector has been initialized.
bool m_Initialized;
// The components of the vector.
double m_data
};
#endif
He is the class that inherits from it
The header
#ifndef gfxVector2_h
#define gfxVector2_h 1
#include "gfxDimensionalUnit.h"
class vnl_double_2;
class gfxPoint2;
class gfxVector2 : public gfxDimensionalUnit<2>
{
public:
gfxVector2();
gfxVector2(const gfxVector2 &right);
// Constructor from a vector of double of 2 elements
gfxVector2(double *vec);
// Constructor from a 2D DimensionalUnit
gfxVector2(const gfxDimensionalUnit<2>& vec);
// Contructor from two values
gfxVector2(double x, double y);
// Constructor from two 2D points, it makes the vector that
// goes from A to B
//gfxVector2(const gfxPoint2& A, const gfxPoint2& B);
// Constructor from a vnl vector
gfxVector2(const vnl_double_2& vec);
// dor multiplication of two vectors
double operator *(const gfxVector2& vec) const;
// returns the norm of the vector
double GetLength() const;
// returns the squared norm of the vector
double GetSquaredLength() const;
// Normalize the vector
const gfxVector2& Normalize();
// return a normalized vector with the same direction and
// sense of this one
gfxVector2 as_unit() const;
// Inverts the vector
gfxVector2 operator -() const;
vnl_double_2 as_vnl() const;
virtual gfxType GetType() const;
};
// Class gfxVector2
inline gfxVector2::gfxVector2(double *vec)
: gfxDimensionalUnit<2>(vec,2)
{
}
inline gfxVector2::gfxVector2(const gfxDimensionalUnit<2>& vec)
: gfxDimensionalUnit<2>(vec)
{
}
inline gfxVector2::gfxVector2(double x, double y)
{
m_data[0] = x;
m_data[1] = y;
m_Initialized = true;
}
inline gfxVector2 gfxVector2::operator -() const
{
return gfxVector2(-m_data[0],-m_data[1]);
}
inline gfxType gfxVector2::GetType() const
{
return GFX_VECTOR2;
}
#endif
And the cpp
#include "gfxVector2.h"
#include "vnl\vnl_double_2.h"
gfxVector2::gfxVector2()
{
}
gfxVector2::gfxVector2(const gfxVector2 &right)
:gfxDimensionalUnit<2>(right)
{
}
gfxVector2::gfxVector2(const vnl_double_2& vec)
{
m_data[0] = vec(0);
m_data[1] = vec(1);
m_Initialized = true; //vnl vectors can't be null.
}
double gfxVector2::operator *(const gfxVector2& vec) const
{
return m_data[0] * vec[0] + m_data[1] * vec[1];
}
double gfxVector2::GetLength() const
{
return sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1]);
}
double gfxVector2::GetSquaredLength() const
{
return m_data[0]*m_data[0] + m_data[1]*m_data[1];
}
const gfxVector2& gfxVector2::Normalize()
{
if(IsNull())
return *this;
double dLength = GetLength();
if ( dLength > GFX_ZERO_TOLERANCE )
{
double dInvLength = 1.0/dLength;
m_data[0] *= dInvLength;
m_data[1] *= dInvLength;
}
else
{
//Defensive assignment.
m_data[0] = 0.0;
m_data[1] = 0.0;
m_Initialized = false;
}
return *this;
}
gfxVector2 gfxVector2::as_unit() const
{
gfxVector2 vec(*this);
return vec.Normalize();
}
vnl_double_2 gfxVector2::as_vnl() const
{
return vnl_vector_fixed<double,2>(m_data);
}
gfxVector2 NullVector2;
mstrecman
Tim Mercer
(The strange thing is that the undecorated name of the reported " _7 $gfxDimensionalUnit@$02@@6B@" string actually seems to be "const gfxDimensionalUnit<3>::`vftable'").
tsg
arse
I'm feeling fairly certain that the problem is in your project or header setup, though. I downloaded the VNL library, compensated the other missing types and compiled a static library from the code you provided. That worked out just fine. Even with use in an external project, everything compiled like a charm.
Could you shed any more light on your setup, or perhaps make your project publicly available
mt2
Rivan56
The specific error that happens when linking another library that uses the given is:
GfxBase.lib(GfxBase.dll) : error LNK2005: "public: __thiscall gfxDimensionalUnit<2>::GetComponents(void)" ( _7 $gfxDimensionalUnit@$02@@6B@) already defined in gfxArcFinder.obj
Aaron Oneal
alphonso
#ifndef gfxDimensionalUnit_h
#define gfxDimensionalUnit_h 1
Tryin2Bgood