C++ Template 特化与重载

特化与重载:

1.重载函数模板:

与普通函数一样,函数模板也可以重载.在重载函数模板的时候,应该把改变限制在一下两种情况:改变参数的数目或者显示地指定模板参数.除此之外,函数的所有重载版本的声明都应该位于该函数被调用的位置之前.

P.S:

类模板是不能被重载的.

2.特化:

1`全局类模板的的特化:

如果要特化一个类模板,就要特化该类模板的所有成员函数.引入全局特化需要用到3个标记序列:template,<和>.还有紧跟在类名称声明后面的就是要进行特化的模板实参.而且必须在类名的后面直接指定.

指定的模板参数列表必须和相应的模板参数列表一一对应,如果模板参数具有缺省模板实参,那么用来替换的模板实参就是可选的.

进行类模板的特化时,每个成员函数都必须重新定义为普通函数(也就是说不能用template<>前缀),原来模板函数中的每个参数也相应地被进行特化的类型取代.

例如:

template<typename T>

class test

{

public:

void foo()

{

///doing

}

}

//特化

template<>

class test<int>

{

public:

void foo();

}

void test<int>::foo()

{

//doing other

}

P.S:

1)特化的实现可以和基本类模板的实现完全不同.

2)可以用全局函数模板特化来代替对应反省模板的某个实例化体,然而,全局模板特化和由模板生成的实例化版本是不能共存与同一个程序中的.如果要试图在同一个文件中使用这两者的话,就会导致一个编译器错误.

2`全局函数模板特化:

全局函数模板特化和类模板特化大体上一致,唯一的区别在于:函数模板特化引入了重载和实参演绎这两个概念.

全局函数模板特化不能包含缺省的实参值.然而,对于基本(即要被特化的)模板所指定的任何缺省参数,显示特化版本都可以应用这些缺省值.

3`全局成员特化:

除了成员模板之外,类模板的成员函数和普通的静态成员变量也可以被全局特化.实现特化的语法会要求给每个外围类模板加上template<>前缀.如果要对一个成员函数模板进行特化,也必须加上另一个template<>前缀.

例如:

template<typename T>

class test

{

public:

void foo()

{

//doing....

}

}

template<>

void test<int>::foo()

{

//do other...

}

4`局部的类模板特化:

类模板也可以被局部热化.可以在特定的环境下指定类模板的特定实现,并且要求某些模板参数仍然必须由用户来定义.如果有多个局部特化同等程度地匹配某个声明,那么该声明就有二义性.

例如:

template<typename T1, typename T2>

class MyClass

{

///...

};

template<typename T>

class MyClass<T, T>

{

///...

};

template<typename T>

class MyClass<T, int>

{

///...

};

template<typename T1, typename T2>

class MyClass<T1*, T2*>

{

///...

};

对于局部特化声明的参数列表和实参列表,存在一些约束,如下:

1)局部特化的实参必须和基本模板的相应参数在种类上(可以是类型,非类型或者模板)是匹配的.

2)局部特化的参数列表不能具有缺省实参.但局部特化仍然可以使用基本类模板的缺省实参.

3)局部特化的非类型实参只能是类型类值,或者是普通的非类型模板参数.而不能是更复杂的依赖型表达式.

4)局部特化的模板实参列表不能和基本模板的参数列表完全等同.