泛化:模板,可以随便指定类型。
特化: 对特殊的类型(类型模板参数)进行特殊的对待,给他开小灶,给它写适合它的专用代码。

一: 类模板特化

<1>类模板全特化
1>常规全特化
必须先有泛化版本,才能存在特化版本。只要涉及特化,一定先存在泛化。
特化版本代码编译器会优先选择。
TC<char, int> tcchar;
tcchar.functest(); //泛化版本

TC<int, int> tcdint;
tcdint.functest(); //int, int的特化版本
//这种特化版本可以任意多;我们目前是写了两个。

2>特化成员函数而不是模板
TC<double, double> tdbldbl; //泛化版本对象, 调用的是泛化版本的构造函数。
tdbldbl.functest(); //因为我们特化了double, double类型的functest函数,所以这里调用的是特化的functest()函数。

template<typename T, typename U>
struct TC  //泛化的TC类模板
{TC(){cout << "TC泛化版本构造函数" << endl;}void functest(){cout << "TC泛化版本" << endl;}
};//当T和U这两个类型模板参数都为int类型时,我们希望做一个特化版本
//全特化:就是所有类型模板参数(这里T和U),都得用具体的类型代表。
template<>  //全特化: 所有类型模板参数都用具体类型代表,所以这里的template后边的<>里为空
struct TC<int, int>  //上边的T绑定到这里的第一个int,上边的U绑定到这里的第二个int
{TC(){cout << "TC<int, int>的特化版本构造函数" << endl;}//在这里可以对该特化版本做单独处理void functest(){cout << "TC<int, int>的特化版本" << endl;}
};template<>  //全特化: 所有类型模板参数都用具体类型代表,所以这里的template后边的<>里为空
struct TC<double, int>  //上边的T绑定到这里的第一个double,上边的U绑定到这里的第二个int
{//在这里可以对该特化版本做单独处理void functest(){cout << "TC<double, int>的特化版本" << endl;}
};template<>  //全特化
void TC<double, double>::functest()
{cout << "double, double的functest()的特化版本" << endl;
}int main()
{TC<char, int> tcchar;tcchar.functest();  //泛化版本TC<int, int> tcdint;tcdint.functest();  //int, int的特化版本TC<double, double> tdbldbl;  //泛化版本对象, 调用的是泛化版本的构造函数。tdbldbl.functest();  //因为我们特化了double, double类型的functest函数,所以这里调用的是特化的functest()函数。return 0;
}

<2>类模板偏特化 (局部特化)
偏特化从两方面说起:一个是从模板参数数量上,一个是从模板参数范围上

1>模板参数数量
TC<double, int, double> tcdi;
tcdi.functest(); //泛化版本
TC<int, int, double> teii;
teii.functest(); //偏特化int, U, double版本

//泛化版本
template <typename T, typename U, typename W>  //带三个类型模板参数
class TCP
{public:TCP(){cout << "TCP泛化版本构造函数" << endl;}void functest(){cout << "TCP泛化版本" << endl;}
};//从参数数量上进行偏特化,我们现在绑2个类型模板参数。留1个模板类型参数。
template<typename U>  //因为另外两个被我绑定到具体类型,所以这里只剩下一个U类型模板参数了。
struct TCP<int, U, double>  //大家注意,这里可以跳着来
{TCP(){cout << "TCP<int, U, double>偏特化版本构造函数" << endl;}void functest(){cout << "TCP<int, U, double>偏特化版本" << endl;}
};int main()
{TCP<double, int, double> tcpdi;  //TCP泛化版本构造函数tcpdi.functest();  //TCP泛化版本TCP<int, int, double> tcpii;  //TCP<int, int, double>偏特化版本构造函数tcpii.functest();  //TCP<int, int, double>偏特化版本return 0;
}

2>模板参数范围上:int, const int(比int小),
原来T,现在T* (从任意类型T索晓伟指针类型T*)
原来是T,现在T&左值引用,或者现在是T&&(右值引用),都叫范围缩小。
TC td;
td.functest(); //泛化版本

TC<double*> tpd;
tpd.functest(); //T*特化版本

TC<const double*> tpd2;
tpd2.functest(); //T*特化版本

TC td3;
td3.functest(); //const T特化版本

TC<int&> tcyi;
tcyi.functest(); //T&左值引用特化版本

TC<int&&> tcyii;
tcyii.functest(); //T&&右值引用特化版本

局部特化,特化完了之后它本质上还是个模板。全特化,特化完了等于一个具体的类了。

//泛化版本
template <typename T>
struct TC
{void functest(){cout << "泛化版本" << endl;}
};//模板参数范围上的特化版本
template <typename T>
struct TC<const T>
{void functest(){cout << "const T特化版本" << endl;}
};template <typename T>
struct TC<T*>  //T*的特化版本,告诉编译器,如果使用指针,就调用这个版本。
{void functest(){cout << "T*特化版本" << endl;}
};template <typename T>
struct TC<T&>  //左值引用的特化版本
{void functest(){cout << "T&特化版本" << endl;}
};template <typename T>
struct TC<T&&>  //右值引用的特化版本
{void functest(){cout << "T&&特化版本" << endl;}
};int main()
{TC<double> td;td.functest();  //泛化版本TC<double*> tpd;tpd.functest();  //T*特化版本TC<const double*> tpd2;tpd2.functest();  //T*特化版本TC<const double> td3;td3.functest();  //const T特化版本TC<int&> tcyi;tcyi.functest();  //T&左值引用特化版本TC<int&&> tcyii;tcyii.functest();  //T&&右值引用特化版本return 0;
}

二:函数模板特化

<1>函数模板全特化
const char* p = “I love China!”;
int i = 12;
tfunc(p, i); //T = const char * , tmprv = const char * & , U = int , tmprv2 = int&

int i = 12;
double db = 15.8f;
tfunc(i, db);

全特化函数模板实际上等价于实例化一个函数模板,并不是等价于一个函数重载

void tfunc<int, double>(int& tmprv, double& tmprv2){} //全特化,等价于实例化一个函数模板

void tfunc(int& tmprv, double& tmprv2){} //重载函数应该长这样

编译器选择最最合适的:普通优先,特化版本,泛化版本;(优先级顺序排列)

如果你传递个字符串给函数模板
函数模板的特化版本中,如果有数组类型模板参数, 指针类型模板参数。
编译器会认为数组类型模板参数比指针类型模板参数更合适。所以编译器会为你选择数组类型的模板参数的特化版本。

<2>函数模板偏特化
函数模板不能偏特化

//函数模板泛化版本
template<typename T, typename U>
void tfunc(T& tmprv, U& tmprv2)
{cout << "tfunc泛化版本" << endl;cout << tmprv << endl;cout << tmprv2 << endl;
}函数模板偏特化
//template<typename U>
//void tfunc<double, U>(double& tmprv, U& tmprv2)  //“tfunc”: 非法使用显式模板参数
//{//  //......
//}//全特化版本,T = int, U = double
template<>
void tfunc(int& tmprv, double& tmprv2)
{cout << "-------------begin---------------" << endl;cout << "tfunc全特化版本int, double" << endl;cout << tmprv << endl;cout << tmprv2 << endl;cout << "-------------end---------------" << endl;
}//重载函数
void tfunc(int& tmprv, double& tmprv2)
{cout << "tfunc重载函数(int, double)" << endl;
}int main()
{const char* p = "I love China!";int i1 = 12;tfunc(p, i1);  //T = const char * , tmprv = const char * & , U = int , tmprv2 = int&int i2 = 12;double db = 15.8f;tfunc(i2, db);return 0;
}

三: 模板特化版本放置位置建议

模板定义、实现都放在一个 .h中;
模板的特化版本和模板的泛化版本都应该放在同一个 .h 文件中。
.h 文件中前面放泛化版本,后面放特化版本。

15.6 模板全特化与偏特化(局部特化)相关推荐

  1. [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

    http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1.  主版本模板类 首先我们来看一段初学者都能看 ...

  2. 模板特化,全特化,偏特化,全部特化,部分特化的含义

    模板特化,任何针对模板参数进一步进行条件限制设计的特化版本.<泛型思维> 全特化就是全部特化,即针对所有的模板参数进行特化.<c++ primer> 偏特化就是部分特化,即针对 ...

  3. 第十天2017/04/21(2、泛型编程:模板 / 全特化、偏特化)

    1.什么是模板? template<class T1,class T2,.....> 类属----类型参数化,又称参数模板使得程序可以从逻辑功能上抽象,把被处理的对象(数据)的类型作为参数 ...

  4. (函数/类模板)的(偏特化/全特化)

    特化的概念 特化,就是将泛型的东东搞得"具体化"一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰或完全被指定了下 ...

  5. C/Cpp / STL / 模板全特化和偏特化

    栗子 #include <iostream>template <typename T1, typename T2> struct Test {void Print() { st ...

  6. C++ 模板的全特化与偏特化

    模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的. 模板分为类模板与函数模板,特化分为全特化与偏特化.全特化就是限定死模板实现的具体类型,偏特化就是如果这 ...

  7. Th4.6:模板全特化、偏特化(局部特化)详述

    本小节回顾的知识点分别是模板全特化.偏特化(局部特化). 今天总结的知识分为以下4个大点: (1)特化与泛化 (2)类模板特化     (2.1)类模板全特化         a)常规全特化      ...

  8. C++ 模板 全特化与偏特化

    C++ 模板 全特化与偏特化 模板 模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性.模版可以分为两类,一个是函数模版,另外一个是 ...

  9. C++模板的全特化和偏特化

    C++模板的全特化与偏特化 全特化 偏特化 例子 总结 全特化 全特化一般用于处理有特殊要求的类或者函数,此时依靠泛型模板无法处理这种情况.,因此全特化可以运用在类模板和函数模板当中.其模板参数列表为 ...

  10. 【C++模板】特化与偏特化 template [partial] specialization

    1 template specialization 模板特化 一般情况下类模板定义如下: template<class Window, class Controller> class Wi ...

最新文章

  1. asp.net读取模版并写入文本文件
  2. 算法导论之用于不相交集合的数据结构
  3. Spring MVC如何接收浏览器传递来的请求参数--request--形参--实体类封装
  4. Pandas学习笔记1(序列部分)
  5. 一次“背锅”和“解锅”后的反思
  6. PCL .stl格式转成.pcd格式点云文件
  7. 电驴v1.2.2.45574最新版官方下载
  8. Java的getbytes()方法使用
  9. apple id两步验证服务器,【安全可靠】Apple ID 两步验证支持中国地区 - 爱应用
  10. 地理坐标系:WGS84和BD09互转
  11. Perfmon监控Windows进程性能
  12. 【MOOC】计算机网络与通信技术笔记(北交)(1)概述
  13. 什么是yum源,yum的工作原理又是什么
  14. python报错(一):takes no arguments
  15. 关于java中的finalize()方法
  16. creator 物理画线
  17. MBA不修“内功”,智能音箱犯后遗症
  18. NGS_RNA-Seq
  19. Unity-动画-动画回调函数接口StateMachineBehaviour
  20. echarts 如何在地图组件上加入南海

热门文章

  1. 2022-11-18 mysql列存储引擎-assert failed on i < m_idx.size() at rc_attr.h:342-问题分析
  2. 7-19 统计人数(2008慈溪) (100分)
  3. 软件测试系列——冒烟测试
  4. 追梦算法网----团队数量
  5. html内嵌式选择器,CSS样式 CSS选择器(Cascading Style Sheet)
  6. 线程2--主线程(main线程)
  7. 神经网络第一篇——感受野的学习、计算与思考
  8. 计算机excel感叹号,excel的文件上有个的感叹号是什么意思?
  9. java mvc外文文献_java spring英文文献和中文翻译
  10. 小视频如何伪原创 抖音合并视频md5