泛型语义
泛型(Generic Programming),即是指具有在多种数据类型上皆可操作的含意。泛型编
程的代表作品 STL 是一种高效、泛型、可交互操作的软件组件。
泛型编程最初诞生于 C++中,目的是为了实现 C++的 STL(标准模板库)。其语言支
持机制就是模板(Templates)。
模板的精神其实很简单:类型参数化(type parameterized),即,类型也是一种参数,
也是一种静多态。 换句话说, 把一个原本特定于某个类型的算法或类当中的类型信息抽掉,
抽出来做成模板参数。
函数模板
引子:重载函数,虽然在一定程度上达到了多类型适应的目的,但是不彻底,且有二义性存在。
#include <iostream> using namespace std; void myswap(int & a, int &b){ int t = a; a = b; b = t; } void myswap(double & a, double &b){ double t = a; a = b; b = t; } int main(){ long a = 2; long b = 3; myswap(a,b); //ambiguous cout<<a<<b<<endl; return 0; }
函数模板
语法:在一个函数的参数表, 返回类型和函数体中使用参数化的类型。
template<typename/class 类型参数 T1, typename/class 类型参数 T2,...>
特点:结构上与普通函数无异,但是在传入参数和返回值上做了泛化
返回类型 函数模板名(函数参数列表) { 函数模板定义体 }
案例:(概念比较抽象,请通过案例来观察其特点)
关于类型,今后我们会在博客的迭代中说明,多个不同类型参数的情况如何处理。
函数模板与普通函数的区别无非就是将函数参数高度抽象化,使其具备处理更多数据类型的能力。
特性小结
1)严格匹配,不存在隐式转化。
2)先实例化,再调用。
3)类型参数可以省略。
4)尺有所长,寸有所短。
原理:
编译器并不是把函数模板处理成能够处理任意类的函数; 编译器从函数模板通过
具体类型产生不同的函数; 编译器会对函数模板进行两次编译: 在声明的地方对模板
代码本身进行编译, 在调用的地方对参数替换后的代码进行编译。
函数模板的应用——将快速排序算法实现模板化
#include <iostream> #include <typeinfo> using namespace std; template<typename T> void quickSort(T * array,int left, int right) { if(left<right) { int low = left; int high = right; T pivot = array[low]; while(low<high) { while(array[high] >= pivot && high>low ) high--; array[low] = array[high]; while(array[low] <= pivot&& high>low) low++; array[high] = array[low]; } array[low] = pivot; quickSort(array,left,low-1); quickSort(array,low+1,right); } } int main() { int array[10] = {1,3,5,7,2,4,6,8,0,9}; quickSort<int>(array,0,9); for(auto i:array) { cout<<i<<endl; } }
函数模板的默认参数
函数模板,在调用时,先实例化为模板函数,然后再调用。当然也可以设置默认类
型的默认值。由于系统强大的自动推导能力,有时默认也没有太大的意义。
template<typename T = int> void quickSort(T * array,int left, int right)
模板特化
就是在实例化模板时,对特定类型的实参进行特殊处理,即实例化一个特殊的实例版本。
template<typename T> int compare( T &a, T &b) template<> int compare < const char * >( const char* &a, const char* &b)
当以特化定义时的形参使用模板时,将调用特化版本,模板特化分为全特化和偏特
化,函数模板的特化,只能全特化;
比如我们在比较两个数的大小时:
#include <iostream> #include <string.h> using namespace std; template<typename T> int compare( T &a, T &b) { if(a > b) return 1; else if(a < b)return -1; else return 0; } //实参为两个 char 指针时, 比较的是指针的大小, //而不是指针指向内容的大小, 此时就需要为该函数模板定义一个特化版本, 即特殊处理的版本: template<> int compare < const char * >( const char* &a, const char* &b) { return strcmp(a,b); } int main() { int a = 3; int b = 5; cout<<compare(a,b)<<endl; string str1 = "abc",str2 ="abc"; cout<<compare(str1,str2)<<endl; char * p1 = "abc",*p2= "def"; cout<<compare(p1,p2)<<endl; cout<<compare(p2,p1)<<endl; return 0; }
关于模板特化的认识
模板特化的原因:当前函数模板的逻辑或者功能,不能满足特定参数的需求。
模板特化的方式:将需要特化的参数提前”布置“到模板中去,提前预定模板,之后传入需要特化的参数时便可以
优先调用经过该参数特化的模板。
适用场景
函数模板,只适用于函数的参数个数相同而类型不同,且函数体相同的情况。如果
个数不同,则不能用函数模板。
原文地址:https://www.cnblogs.com/wangkeqin/p/9240608.html