C++ 目前支持两大类template基本类型: class templates和function templates。这个分类还包括member templates。Templates的声明与一般class和functions的声明类似,差别在于templates声明语句有一个参数化子句(parameterization clause):
template<...parameters here...>
也可能像下面:
export template<...parameters here...>
模板参数的声明先放一放,以下实例展示两种templates,一种是在class之内:也就是member templates,一种是在class之外且在namespace scope之内(全局 scope也可以看做是一种名空间scope):
template <typename T>
class List { //namespace scope class template
public:
template <typename T2> //member function template
List (List<T2> const &);
...
};
template <typename T>
template <typename T2>
List<T>::List (List<T2> const&b) //class外的 member function template
{
...
}
template <typename T>
int length (List<T> const&)l //namespace scope function template
class Collection {
template <typename T> //class 内的member class template
class Node{
...
};
template <typename T> //class内的member class template, 但是无定义
class Handle;
template <typename T> // inner class, member function template,inline
T* alloc() {
...
}
...
};
template <typename T> //class外的member class template
class Collection::Handle {
...
}
类似地,我们可以有union templates(可看作是class template的一种)
template <typename T>
union AllocChunk
{
T object;
unsigned char bytes[sizeof(T)];
};
函数模板function template可以有预设的调用自变量(default call argument):
template <typename T>
void report_top (Stack<T> const&, int number=10);
template <typename T>
void fill (Array<T>*, T const& = T() );
除了两种template基本类型,另有三种声明也可以被参数化,它们都有类似写法。三者均相当于class template的成员定义:
1) class templates的成员函数定义
2)class templates的nested class members定义
3)class templates的static 成员变量定义
1. 虚拟成员函数Virtual Member Function
Member function template不能声明成virtual。原因是通常虚拟函数调用机制使用一个大小固定不变的表格,其中每一个条目entry记录一个虚拟函数入口entry point。然而直到整个程序编译完成,编译器才能知道有多少个member function template被实例化。
然而一般的class template members可以是虚拟函数,因为当class被实例化时,那些members的数量已经固定:
template <typename T>
class Dynamic{
public:
virtual ~Dynamic(); //OK;每个Dynamic<T>都有一个析构函数
template <typename T2>
virtual void copy(T2 const&); //Error: 编译器此时并不知道在一个Dynamic<T>中要产生多少
//个 copy()实例。
};
2. 模板的链接(Linkage)
每个template在其作用域scope内必须有一个独一无二的名称,除非是重载的overloaded function template。特别注意的是,class template 不能和其他种类的名称共享同一个名称,这点与一般non-template的class不同。比如:
int C;
class C; //ok
int X;
template <typename T>
class X; //Error;
struct S;
template <typename T>
class S; //Error;
Template名称需要链接,但不能够使用C链接方式,默认是C++链接方式:
extern “C++” template <typename T>
void normal(); //上面是正常链接方式,extern “C++”也可省略不写。
extern "C" template <typename T>
void invalid(); //上面是无效的,不能使用C链接方式。
Template通常使用外部链接(external linkage)。唯一例外的是static namespace scope function templates:
template <typename T>
static void internal(); //与另一文件中的同名template无关。
3. 主模板、原始模板Primary Templates
正规标准的template声明语句声明的是primary templates。这一类语句在template名称后面并不添加由角括号括起来的template argument list:
template <typename T> class Box; //OK: primary template
template <typename T> class Box<T>; //Error
template <typename T> void translator(T*); //OK
template <typename T> void translate<T>(T*); //Error