泛型编程是指独立与任何类型的方式编写代码。泛型编程和面向对象编程,都依赖与某种形式的多态。面向对象编程的多态性在运行时应用于存在继承关系的类,一段代码能够能够忽略基类和派生类之间的差别。在泛型编程中,编写的代码能够用做多种类型的对象。面向对象编程所依赖的多态性称为运行时多态性,泛型编程所依赖的多态性称为编译时多态性或参数式多态性。 html
1 template<typename T> 2 inline bool isEqual(const T& t1, const T& t2) { 3 return t1 == t2; 4 }
1 const size_t MAXSIZE = 100; 2 template<class T> 3 class Stack{ 4 private: 5 T elements[MAXSIZE]; 6 public: 7 //others 8 };
1 template<typename T,int X = 5> 2 inline bool isEqualToX(const T& a) { 3 return a == X; 4 } 5 6 template<class T,int MAXSIZE=100> 7 class Stack { 8 private: 9 T elements[MAXSIZE]; 10 public: 11 //others 12 };
有时为了须要,针对特定的类型,须要对模板进行特化,也就是特殊处理。 例如,stack类模板针对bool类型,由于实际上bool类型只须要一个二进制位,就能够对其进行存储,使用一个字或者一个字节都是浪费存储空间的.。特化必须在同一命名空间下进行,能够特化类模板也能够特化函数模板,但类模板能够偏特化和全特化,而函数模板只能全特化。模板的偏特化是指须要根据模板的某些但不是所有的参数进行特化。严格的来讲,函数模板并不支持偏特化,但因为能够对函数进行重载,因此能够达到相似于类模板偏特化的效果。模板实例化时会优先匹配”模板参数”最相符的那个特化版本。template < >告诉编译器这是一个特化的模板。ios
1 template<class T,int MAXSIZE=100> 2 class Stack { 3 private: 4 T elements[MAXSIZE]; 5 public: 6 //others 7 }; 8 9 //template specializations aim at bool 10 template<> 11 class Stack<bool>{ 12 13 };
1 template<typename T> 2 inline bool isEqual(const T t1, const T t2) { 3 return t1 == t2; 4 } 5 6 //针对int型的指针作特化 7 template<> 8 inline bool isEqual(const int* p1,const int* p2){ 9 return *p1 == *p2; 10 }
类模板的偏特化,例如c++标准库中的类vector的定义,这个偏特化的例子中,一个参数被绑定到bool类型,而另外一个参数仍未绑定须要由用户指定。c++
1 template <class T, class Allocator> 2 class vector { // … // }; 3 template <class Allocator> 4 class vector<bool, Allocator> { //…//};
函数模板的偏特化,严格的来讲,函数模板并不支持偏特化,但因为能够对函数进行重载,因此能够达到相似于类模板偏特化的效果。根据重载规则,对(a)进行重载。若是将(a)称为基模板,那么(b)称为对基模板(a)的重载,而非对(a)的偏特化。C++的标准委员会仍在对下一个版本中是否容许函数模板的偏特化进行讨论。
template <class T> void f(T); (a)
template < class T> void f(T*); (b)编程
3.1 隐式实例化。在使用模板函数和模板类时,不存在指定类型的模板函数和模板类的实体时,由编译器根据指定类型参数隐式生成模板函数或者模板类的实体称之为模板的隐式实例化。函数模板隐式实例化指的是在发生函数调用的时候,若是没有发现相匹配的函数存在,编译器就会寻找同名函数模板,若是能够成功进行参数类型推演,就对函数模板进行实例化。类模板隐式实例化指的是在使用模板类时才将模板实例化。函数
3.2 显示实例化。显示实例化也称为外部实例化。在不发生函数调用的时候将函数模板实例化,或者在不适用类模板的时候将类模板实例化称之为模板显示实例化。对于函数模板而言,不论是否发生函数调用,均可以经过显示实例化声明将函数模板实例化,定义函数模板为:template函数返回类型 函数模板名<实际类型列表>(函数参数列表),显示实例化为template void func<int>(const int&);类模板的显示实例化,对于类模板而言,不论是否生成一个模板类的对象,均可以直接经过显示实例化声明将类模板实例化,定义类模板格式为:template class 类模板名<实际类型列表>,显示实例化为template class theclass<int>;优化
3.3 匹配规则spa
(1) 类模板的匹配规则。最优化的优于次特化的,即模板参数最精确匹配的具备最高的优先权,每一个类型均可以用做普通型(a)的参数,但只有指针类型才能用做(b)的参数,而只有void*才能做为(c)的参数。.net
template <class T> class vector{//…//}; // (a) 普通型
template <class T> class vector<T*>{//…//}; // (b) 对指针类型特化
template <> class vector <void*>{//…//}; // (c) 对void*进行特化指针
(2) 函数模板的匹配规则。非模板函数具备最高的优先权。若是不存在匹配的非模板函数的话,那么最匹配的和最特化的函数具备高优先权rest
template <class T> void f(T); // (d)
template <class T> void f(int, T, double); // (e)
template <class T> void f(T*); // (f)
template <> void f<int> (int) ; // (g)
void f(double); // (h)
bool b;
int i;
double d;
f(b); // 以 T = bool 调用 (d)
f(i,42,d) // 以 T = int 调用(e)
f(&i) ; // 以 T = int* 调用(f)
f(d); // 调用(g)
参考:http://www.cnblogs.com/qicosmos/p/4325949.html
可变参数模板是C++11新增的特性之一,它对参数高度泛化,他能表示0到任意个数、任意类型的参数。可变模板参数以前会带有省略号,把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。咱们没法直接获取参数包args中的每一个参数的,只能经过展开参数包的方式来获取参数包中的每一个参数,这是使用可变模版参数的一个主要特色。可变模版参数和普通的模版参数语义是一致的,因此能够应用于函数和类,便可变模版参数函数和可变模版参数类,然而,模版函数不支持偏特化,因此可变模版参数函数和可变模版参数类展开可变模版参数的方法还不尽相同。
1 #include <iostream> 2 using namespace std; 3 //递归终止函数 4 void print() 5 { 6 cout << "empty" << endl; 7 } 8 //展开函数 9 template <class T, class ...Args> 10 void print(T head, Args... rest) 11 { 12 cout << "parameter " << head << endl; 13 print(rest...); 14 } 15 16 17 int main(void) 18 { 19 print(1,2,3,4); 20 return 0; 21 }
1 template <class T> 2 void printarg(T t) 3 { 4 cout << t << endl; 5 } 6 7 template <class ...Args> 8 void expand(Args... args) 9 { 10 int arr[] = {(printarg(args), 0)...}; 11 } 12 13 expand(1,2,3,4);
可变参数模板类的参数包展开的方式和可变参数模板函数的展开方式不一样,可变参数模板类的参数包展开须要经过模板特化和继承方式去展开,展开方式比可变参数模板函数要复杂。可变参数模板类是一个带可变模板参数的模板类,好比C++11中的元祖std::tuple就是一个可变模板类,它的定义以下,这个可变参数模板类能够携带任意类型任意个数的模板参数。
1 template< class... Types > 2 class tuple; 3 std::tuple<int> tp1 = std::make_tuple(1); 4 std::tuple<int, double> tp2 = std::make_tuple(1, 2.5); 5 std::tuple<int, double, string> tp3 = std::make_tuple(1, 2.5, “”); 6 std::tuple<> tp;//可变参数模板的模板参数个数能够为0个,因此下面的定义也是也是合法的:
参考