#include<iostream>
using std::cout;
using std::endl;
using std::ostream;
template<typename S>
class Vec{
private:
int len;
S *theVec;
public:
template<typename T>
Vec(T* x, int l);
template<typename T>
Vec(Vec<T> x);
int getLen(){ return len;}//accessor function needed
//since len is private
S *getVec(){//return a COPY of the array in Vec object
if ((theVec==NULL)or(len==0))
return NULL;
else{
S* v=new S[len];
for(int i=0; i< len; ++i)
v[i]=theVec[i];
return v;
}
}
//inline non-member friend operators friend Vec operator+(const Vec &x, const Vec &y){
Vec z=Vec(x);
for (int i=0;i<=y.len;++i)
z.theVec[i]=x.theVec[i] + y.theVec[i];
return z;
}
oh, this is just the first part of the whole code, and the definition is in the latter part. Because it does not relate to my question, I cut it off to save space. Thanks:)
Thanks for your kind reply:) I am a newbie, so, to make things clear: when you say template definition must always be inline, do you mean that I must provide the definition when the constructor appears at the first time? This is the whole code:
#ifndef VEC_H
#define VEC_H
#include<iostream>
using std::cout;
using std::endl;
using std::ostream;
template<typename S>
class Vec{
private:
int len;
S *theVec;
public:
template<typename T>
Vec(T* x, int l);// Allows us to define, e.g. complex Vec
//out of, say a float array
template<typename T>
Vec(Vec<T> x); //template copy constructor: Same as above
int getLen(){ return len;}//accessor function needed
//since len is private
S *getVec(){//return a COPY of the array in Vec object
if ((theVec==NULL)or(len==0))
return NULL;
else{
S* v=new S[len];
for(int i=0; i< len; ++i)
v[i]=theVec[i];
return v;
}
}
//inline non-member friend operators
friend Vec operator+(const Vec &x, const Vec &y){
Vec z=Vec(x);
for (int i=0;i<=y.len;++i)
z.theVec[i]=x.theVec[i] + y.theVec[i];
return z;
}
friend Vec operator*(const S &alpha, const Vec & xx){
Vec zz=Vec(xx);
for(int i=0; i<xx.len; ++i)
zz.theVec[i]=alpha*zz.theVec[i];
return zz;
}
//This overloading of << for Vec<S> assumes that << is
//also defined for S types. So, e.g. when you define
// Vec<complex> z;
// then it is assumed for complex types << is already
// defined.
friend ostream &operator <<(ostream &out, const Vec &x){
for (int i=0; i< x.len;++i)
out<<x.theVec[i]<<endl;
return out;
}
};
template<typename S>
template<typename T>
Vec<S>::Vec(Vec<T> xx):
len(xx.getLen()),
theVec(new S[xx.getLen()]){
//The following for loop assumes conversion from T to S
//is available. So for instance, if T is float and S is complex,
//then there should be 1-argument constructor turning float
//to complex. Also note that
// if T and S are different types,then Vec<T> and Vec<S> are different classes,
// so "len" and
//"theVec" members of Vec<T> are invisible to Vec<S>. That is
//why we cannot write: theVec[i]= xx.theVec[i].
T* xv=xx.getVec();
for(int i=0; i<len;++i){
theVec[i]=xv[i];
}
}
template<typename S>
template<typename T>
Vec<S>::Vec(T* x, int l):
len(l){
theVec=new S[l];
for(int i=0; i<l; ++i)
theVec[i]=x[i];//assumes conversion from T to S
}
#endif
It provides the definition outside the class scope, but still works. So do I think it in the wrong way? Thanks:)
It still works because both the declaration (in the class) and the definition (outside the class) are visible at the same time. If you were to include that in multiple source files the linker would complain that you defined it more than once, so you would then try to define the functions in their own source file. This is where the trouble comes: you can't without knowing all the template instantiations your entire code will use. You see, the compiler instantiates templates on the fly, so it needs the source code to work with - if it doesn't have that, you're going to have issues with the linker yes again.
So,long story short, if you ever use templates, always define them inline. This includes all member functions inside of a templated class, and it excludes prototypes for templated functions.
OK, so whenever I use the templates, I should always provide the definition at the first time to avoid any potential mistake. Thanks for your timely reply, I really appreciate it:)