函数新手的冷门——函数模板(全:包括实例化和具体化)

简介: 函数新手的冷门——函数模板(全:包括实例化和具体化)

可能有的人像以前的码神一样,学了一年多都不知道函数模板究竟是个什么东东,究竟有什么用,这可谓是秋名山一路下来,不知道有个排水渠过湾一样,哈哈,话不废话,直接上正题了。
定义
函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。
这他妈的,god知道是什么东西啊!

那就写用法吧:
这里引用c++primer中的一个案例swap函数

void swap(int &a,int &b)//int 
{
    int temp;
    temp=a;
    a=b;
    b=temp;
}
void swap1(double &a,double &b)
{
    int temp;
    temp=a;
    a=b;
    b=temp;
}

可以看出,我为了实现交换的操作,需要写俩个函数,尽管他们的用途几乎是一致的,此时周董的黑白ae86——函数模板就来了,再看:

template <class T>
void Swap(T & x, T & y)
{
    T tmp = x;
    x = y;
    y = tmp;
}

这个就是函数模板,书中的解释是这样的
T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。

下面给大家写一个完整的模板

#include <iostream>
using namespace std;
template<class T>
//其中class可以替换为typename
//template<typename T>
void swap(T & x, T & y)
{
    T tmp = x;
    x = y;
    y = tmp;
}
int main()
{
    int n = 1, m = 2;
    swap(n, m);  //编译器自动生成 int 函数
    double f = 1.2, g = 2.3;
    swap(f, g);  //编译器自动生成  double 函数
    return 0;
}

其中的原理就是,编译器找不到,函数Swap的类型,但是发现,我们传入的n,m都是int类型,所以自己用int来代替函数模板中的T

要实现函数模板的理解,我们还应该了解专业术语:

  1. 实例化:1 实例化

实例化有两种形式,分别为显式实例化和隐式实例化。模板并非函数定义,实例式函数定义。

1.1 显式实例化(explicit instantiation)
显式实例化意味着可以直接命令编译器创建特定的实例,有两种显式声明的方式。

比如存在这么一个模板函数

template
void Swap(T &a, T &b)

第一种方式是声明所需的种类,用<>符号来指示类型,并在声明前加上关键词template,如下:
template void Swap(int &, int &);

第二种方式是直接在程序中使用函数创建,如下:

Swap(a,b);

显式实例化直接使用了具体的函数定义,而不是让程序去自动判断。

1.2 隐式实例化(implicit instantiation)
隐式实例化比较简单,就是最正常的调用,Swap(a,b),直接导致程序生成一个Swap()的实例,该实例使用的类型即参数a和b的类型,编译器根据参数来定义函数实例。

  1. 具体化:思考这么一个问题,当前的Swap模板交换输入的两个对象,可能式基本类型也可能式自定义类。如果有这么一个需求,需要交换自定义类里的某一个属性而不是整个类,那么Swap模板就不可用,因为Swap模板交换的是整个类。

显式具体化将不会使用Swap()模板来生成函数定义,而应使用专门为该特定类型显式定义的函数类型。有两种定义形式,如下,其中job为用户自定义类
template <> void Swap(job &a, job &b)
template <> void Swap(job &a, job &b)
显式具体化在声明后,必须要有具体的实现,这是与显示实例化不同的地方。

下面我们再来模仿一个程序来具体看一下

#include<iostream>
#include<string>
using namespace std;
 
struct job
{
    string name;
    int salary;
    job(string _name,int _salary):name(_name),salary(_salary){};
};
 
//template prototype
template <typename T>
void Swap(T &a, T &b){
    T temp;
    temp = a;
    a = b;
    b = temp;
}
 
//explict specialization for job 显式具体化
template <> void Swap(job &a, job &b)
{
    int temp;
    temp = a.salary;
    a.salary = b.salary;
    b.salary = temp;
}
 
template void Swap<int>(int &, int &);
int main()
{
    char a = 'a', b = 'b';
    cout<<"a: "<<a<<" ; b: "<<b<<endl;
    Swap(a,b);  //1 implicit template instantiation for char 隐式实例化
    cout<<"a: "<<a<<" ; b: "<<b<<endl;
 
    int c = 1, d = 2;
    cout<<"c: "<<c<<" ; d: "<<d<<endl;
    Swap(c,d);  //2 use explicit template instantiation for int 显式实例化
    cout<<"c: "<<c<<" ; d: "<<d<<endl;
   
    Swap<int>(c,d);  //3 use explict template instantiation for int 显式实例化
    cout<<"c: "<<c<<" ; d: "<<d<<endl;
    
    job e("lucy",100), f("bob",200);
    cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
    Swap(e,f);  //use explict specialization for job 调用显式具体化
    cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
}

如果感觉不错,欢迎点赞评论!

相关文章
|
小程序 前端开发 iOS开发
uView内置样式
uView内置样式
256 1
|
NoSQL 前端开发 Java
基于springboot的学生成绩在线管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目.
基于springboot的学生成绩在线管理系统(部署文档+数据库表结构文档)。Javaee项目,springboot项目.
|
Java API
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
6764 3
JDK API文档中文版(1.6、1.8、1.9)(附百度网盘下载地址)
|
安全 网络架构
|
12月前
|
搜索推荐 Java Go
希尔排序:优化的插入排序
希尔排序:优化的插入排序
198 2
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
824 9
|
存储 关系型数据库 MySQL
MySQL表空间结构与页、区、段的定义
一、概念引入 1、页 InnoDB是以页为单位管理存储空间的,在InnoDB中针对不同的目的设计了各种不同类型的页面。如下(省略了FIL_PAGE或FiL_PAGE_TYPE的前缀):
|
机器学习/深度学习 自然语言处理 数据处理
通过深度学习识别情绪
通过深度学习识别情绪(Emotion Recognition using Deep Learning)是一项结合多模态数据的技术,旨在通过分析人类的面部表情、语音语调、文本内容等特征来自动识别情绪状态。情绪识别在人机交互、健康监测、教育、娱乐等领域具有广泛的应用。
1375 8
|
消息中间件 存储 缓存
一文了解清楚kafka消息丢失问题和解决方案
今天分享一下kafka的消息丢失问题,kafka的消息丢失是一个很值得关注的问题,根据消息的重要性,消息丢失的严重性也会进行放大,如何从最大程度上保证消息不丢失,要从生产者,消费者,broker几个端来说。
644 0
|
搜索推荐 程序员 开发工具
Emacs Verilog mode 简单使用指南
【6月更文挑战第17天】Emacs Verilog mode 提升Verilog编程体验,提供语法高亮、代码补全、自动缩进等功能。安装可通过`M-x package-install RET verilog-mode`。常见问题包括补全不生效、高亮不准确,可通过调整配置解决。支持模板插入、代码折叠、错误高亮、代码跳转。通过个性化配置、整合Git、集成其他工具和社区资源,实现高效Verilog开发。Emacs学习曲线虽陡,但效能提升显著。
382 4