模板作为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. 第一章:模型层 - 10:不返回QuerySets的API

    以下的方法不会返回QuerySets,但是作用非常强大,尤其是粗体显示的方法,需要背下来. 方法名 解释 get() 获取单个对象 create() 创建对象,无需save() get_or_crea ...

  2. 生产环境中使用Kibana

    在 Kibana 中使用 X-Pack 使用 X-Pack 安全模块 控制用户通过 Kibana 可以访问哪些 Elasticsearch 数据. 当安装 X-Pack 时,Kibana 用户必须登陆 ...

  3. influxDB2.2

    下载安装 下载地址 下载后在解压目录中,输入cmd执行exe文件 浏览器访问localhost:8086 选择快速开始,填写用户信息,组织信息 相关概念 InfluxDB是一个由InfluxData开 ...

  4. 驱动开发:通过Async反向与内核通信

    在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒 ...

  5. 聊聊Vim的工作原理

    聊聊Vim的工作原理 日常里一直在用Vim这个编辑器,前阵子学习关于Linux中的fd(文件描述符)时,发现vim的进程描述符会比上一个自动加一,后续了解到vim的工作原理后,解开了这个疑问,所以记录 ...

  6. [s905l3]性价比神机mgv3000全网首拆,刷armbian实现更多价值!

    最近花55淘了一台mgv3000,s905l3,2+16G带蓝牙,真的性价比没得说 S905L3 工艺28nm差于s905l3a 主频1.9Ghz,超频可以达到2Ghz,GPU是Mail450,当服务 ...

  7. Python 实验报告(第三周)

    一.实验目的和要求 1.熟练运用常见选择结构: 2.熟练运用for循环和while循环: 3.理解带else语句的循环结构执行过程和break.continue语句在循环中的作用. 二.实验环境 软件 ...

  8. ARC148游记

    A - mod M 题目链接 这道题我们可以首先对于所有的数 $%2$ ,可以证明出答案最多不超过 $2$ ,此时我们就可以把问题转化为:是否存在一个数使得序列 $a$ 中所有元素减去这个数之后的最大 ...

  9. CentOS部署MySQL

    Linux上安装MySQL 第一步:确保服务器在最新的状态(可有可无) [root@chenstudy ~]# yum -y update 第二步:检测系统是否自带安装MySQL 我之前安装过MySQ ...

  10. 设计一个网上书店,该系统中所有的计算机类图书(ComputerBook)每本都有10%的折扣,所有的语言类图书(LanguageBook)每本都有2元的折扣,小说类图书(NovelBook)每100元

    现使用策略模式来设计该系统,绘制类图并编程实现 UML类图 书籍 package com.zheng; public class Book { private double price;// 价格 p ...