模板作为C++泛型编程的基础十分重要,其使得一份代码能用于处理多种数据类型。而有些时候,我们会希望对一些特定的数据类型执行不同的代码,这时就需要使用模板特例化(template specialization)。

函数模板特例化

首先说一个重要的,函数模板的特例化并不是函数重载,每一个特例化实际上是提供了另一个模板定义式,因此特例化不影响函数匹配。

特例化一个函数模板时,必须为模板中的每个参数都给出实参,关键字template后跟一个<>

类模板特例化

类模板中,提供所有实参时叫做全特化,类模板的全特化和函数模板的特例化上没有什么不同(除了一个是类模板一个是函数模板:D)

与函数模板必须为每个模板参数提供实参不同,类模板支持部分特例化,也叫偏特化(partial specialization)

当定义类模板的偏特化版本时,模板参数只需包含原模板中那些还未确定类型的模板参数,在类名之后需要添加<>,且需要按对应位置填入实参。

template<typename T, typename P>
class test {
public:
test() { cout << "这是未特化的类模板\n"; }
}; template<typename P>//T被特化为bool类型,template<>中无需typename T
class test<bool,P> {
public:
test() { cout << "这是bool偏特化的类模板\n"; }
}; template<>//全特化,template<>可以为空
class test<int*, int*> {
public:
test(){ cout << "这是接受两个指针类型的全特化的类模板\n"; }
}; {
test<int*, int> t1;//会调用未特化的类模板
test<bool,int> t2;//会调用bool偏特化
test<int*, int*> t3;//全特化版本
}
#include <iostream>

using namespace std;

template<typename T>
class MyVector { public:
MyVector<T>() { cout << "MyVector<T>()" << endl; } }; //针对 char * 模板特例化
template<>
class MyVector<char *> { public:
MyVector() { cout << "MyVector<char *>" << endl; } }; //模板特例化,只针对指针类型提供的部分特例化,只知道指针,但是什么指针不知道
template<typename Ty>
class MyVector<Ty*> { public:
MyVector() { cout << "MyVector<Ty *>" << endl; } }; //template<>
//class MyVector<int(*)(int, int)> {
//public:
// MyVector() { cout << "int (*)(int,int )" << endl; }
//
//}; //template<typename T>
//class MyVector<T(*)(T, T)> {
//public:
// MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; }
//
//};
//
//template<typename R1, typename R2, typename R3>
//class MyVector<R1(*)(R2, R3)> {
// public:
// MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; }
//
//}; //template<typename R1, typename R2, typename R3>
//class MyVector<R1(R2, R3)> {
// public:
// MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; }
//
//}; int sum(int x, int y) {
return x + y;
} int main() { MyVector<int> v1; //缺省模板 MyVector<char *> v2;// char * 特例化模板 MyVector<int *> v3;// 使用部分特例化 class MyVector<Ty*> MyVector<int (*)(int,int)> v4; // 使用部分特例化 class MyVector<Ty*> ,int (*)(int,int) 指向函数的指针 // 如何针对 MyVector<int (*)(int,int)> v4;写一个完全特例化版本? 写法如下
/*
template<>
class MyVector<int(*)(int, int)> {
public:
MyVector() { cout << "int (*)(int,int )" << endl; } };
*/ // 如何针对 MyVector<int (*)(int,int)> v4;写一个部分特例化版本? 写法如下 两种 /* 写法1
MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3 提供部分特例化
template<typename T>
class MyVector<T(*)(T, T)> {
public:
MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; } };
*/ /*
写法2
MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3 提供部分特例化
template<typename R1, typename R2, typename R3>
class MyVector< R1(*)(R2, R3) >
{
public:
MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; } };
*/ MyVector<int(int, int)> v5; //元素是函数对象类型,使用默认的函数版本,也可以使用如下方式 /*
template<typename R1, typename R2, typename R3>
class MyVector<R1(R2, R3)>//针对函数类型,进行部分特例化,有一个返回值,有两个形参
{
public:
MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; } };
*/ //函数指针类型
typedef int (*PFUNCTION) (int, int);
PFUNCTION pf1 = sum;
pf1(12, 13); //函数类型
typedef int PFUNCTION2 (int, int);
PFUNCTION2 * pf2 = &sum;
(*pf2)(12, 13); system("pause");
//有完全特例化能匹配就用完全特例化版本,有部分特例化版本就用部分特例化,再没有就用缺省模板
return 0;
}

//问题:这种写法可以,但是 typename T 这种方式 范围太大了!!优化如下
template<typename T>
void function(T _t) {
cout << typeid(T).name() << endl;
} template<typename R, typename R1, typename R2>
//细分到可以取出返回值类型R1,形参1类型R2,形参2类型R3 还可以继续细分 如下
void function(R1(*)(R2,R3)) { cout << typeid(R1).name() << endl;
cout << typeid(R2).name() << endl;
cout << typeid(R3).name() << endl; } //效果,继续细分到可以取出返回值类型R1,哪个类类型T,形参1类型R1,形参2类型R2 Good
template<typename R, typename T, typename R1, typename R2> void function3(R1(T::*)(R2, R3)) { cout << typeid(T).name() << endl;
cout << typeid(R1).name() << endl;
cout << typeid(R2).name() << endl;
cout << typeid(R3).name() << endl; } class Test { public:
int sum(int x, int y) { return x + y; } }; int main() { function3(&Test::sum);
}

<五>模板的完全特例化和非完全特例化的更多相关文章

  1. Apache Sqoop 结构化、非结构化数据转换工具

    简介: Apache Sqoop 是一种用于 Apache Hadoop 与关系型数据库之间结构化.非结构化数据转换的工具. 一.安装 MySQL.导入测试数据 1.文档链接:http://www.c ...

  2. c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters

    类模板的非类型模板参数 函数模板的非类型模板参数 限制 使用auto推断非类型模板参数 模板参数不一定非得是类型,它们还可以是普通的数值.我们仍然使用前面文章的Stack的例子. 类模板的非类型模板参 ...

  3. 特例模式(Special Case Pattern)与空对象模式(Null Pointer Pattern)—— 返回特例对象而非 null

    返回 null 值,基本上是在给自己增加工作量,也是给调用者添乱.只有一处没有检查返回的是否为 null,程序就会抛 NullPointerException 异常. 如果你打算在方法中返回 null ...

  4. Hadoop基础-Apache Avro串行化的与反串行化

    Hadoop基础-Apache Avro串行化的与反串行化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Apache Avro简介 1>.Apache Avro的来源 ...

  5. JS 函数的柯里化与反柯里化

    ===================================== 函数的柯里化与反柯里化 ===================================== [这是一篇比较久之前的总 ...

  6. 浅谈html语义化标签,Html5新增语义化标签

    Html语义化标签,Html5新增语义化标签 自己在学习的期间,整理了下html关于语义化标签的一些知识,列的不是很全. 希望大家有新的见解可以给我留言,我会补充上去,谢谢大家 1.什么是语义化标签? ...

  7. DevExpress 14.2 批量汉化 以及客户端的汉化

    DXperience汉化方法介绍 运用慧都提供的DXperience汉化包,能将最新版本的DXperience WinForm和ASP.NET控件界面.弹出框.右键菜单等汉化成中文,且能根据自己的需求 ...

  8. JS的防抖,节流,柯里化和反柯里化

    今天我们来搞一搞节流,防抖,柯里化和反柯里化吧,是不是一看这词就觉得哎哟wc,有点高大上啊.事实上,我们可以在不经意间用过他们但是你却不知道他们叫什么,没关系,相信看了今天的文章你会有一些收获的 节流 ...

  9. web标签语义化的理解_web语义化是什么意思

    web语义化是什么? Web语义化,使用语义恰当的标签,可以让页面具有良好的结构,页面元素具有良好的含义,从而让人和机器都能快速理解.语义化的web页面一方面可以让机器在更少的人类干预情况下收集并研究 ...

  10. 玩转Django2.0---Django笔记建站基础五(模板)

    第五章 模板 Django作为web框架,需要一种很便利的方法去动态地生成HTML网页,因此有了模板这个概念.模板包含所需HTML的部分代码以及一些特殊语法 Django可以配置一个或多个模板引擎(甚 ...

随机推荐

  1. Compass- 图形化界面客户端

    到MongoDB官网下载MongoDB Compass, 地址: https://www.mongodb.com/download-center/v2/compass?initial=true 如果是 ...

  2. AlertManager 之微信告警模板,UTC时间错8个小时的解决办法

    注意事项: alertmanager中的web页面显示的报警时间是UTC时间,错8个小时,企业微信报警模板中已经修改过来了 下面配置可以作为参考: 1.prometheus操作 1.1 配置告警规则, ...

  3. http和https分别是什么?

    http中文名:超文本传输协议英文名:Hyper Text Transfer Protocol解释:是一个简单的请求-响应协议,它通常运行在TCP之上.它指定了客户端可能发送给服务器什么样的消息以及得 ...

  4. 【前端必会】tapable、hook,webpack的灵魂

    背景 什么是tapable.hook,平时做vue开发时的webpack 配置一直都没弄懂,你也有这种情况吗? 还是看源码,闲来无聊又看一下webpack的源码,看看能否找到一些宝藏 tapable和 ...

  5. [题解] Codeforces Global Round 22 1738 A B C D E F 题解

    很久没rated打过cf的比赛了,这次打得还行,至少进前100了 点我看题 A. Glory Addicts 把类型0的数放进数组a里,类型1的数放进数组b里.如果\(|a|=|b|\),你可以把所有 ...

  6. androidmanifest.xml 反编译

    androidmanifest.xml 反编译 去除更新只修改androidmanifest.xml内容 解压apk文件后得到这个文件androidmanifest.xml windwos安装java ...

  7. ArcMap布局添加图表问题

    在ArcMap分析制图过程中,经常会产生一些图表,然而在布局中添加这些图表会发现一些意想不到的问题. 问题重现 将图表直接添加到布局会发现图表有黑底,这在我们布局出图中是十分不美观的,这该如何解决呢? ...

  8. POJ3311 Hie with the Pie(状压DP,Tsp)

    本题是经典的Tsp问题的变形,Tsp问题就是要求从起点出发经过每个节点一次再回到起点的距离最小值,本题的区别就是可以经过一个节点不止一次,那么先预处理出任意两点之间的最短距离就行了,因为再多走只会浪费 ...

  9. day09-2视图和用户权限

    视图和用户权限 1.视图(view) 看一个需求 emp表的列信息很多,有些信息是个人重要信息(比如:sal.comm.mgr.hiredate),如果我们希望某个用户只能查询emp表的empno.e ...

  10. 工厂方法在Spring源码中的运用

    我们都知道Spring中IOC是使用的工厂模式,但是对于实现细节就一知半解了,今天这篇文章就带大家解读Spring中是如何使用工厂模式的. 在上篇文章中我们懂了什么是工厂模式,这篇文章就带着学过的概念 ...