C++学习之函数模板的使用详解
C++函数模板
template<typename T> void Swap(T &a ,T &b) { T temp; temp = a; a = b; b = temp; }
在使用模板函数时,编译器根据实际的类型生成相应的函数定义。
重载的模板
并非所有的类型都使用相同的算法,可以像重载常规函数那样重载模板函数定义。
template<typename T> void Swap(T &a ,T &b); //#1 template<typename T> void Swap(T *a ,T *b,int n);//#2 最后一个参数是具体类型 int main() { int i =10,j=20; Swap(i,j);//使用#1 const int Lim = 8; int d1[Lim]={0,1,2,3,4,5,6,7}; int d2[Lim]={7,6,5,4,3,2,1,0}; Swap(d1,d2,Lim);//使用#2 } template<typename T> void Swap(T &a ,T &b) { T temp; temp = a; a = b; b = temp; } template<typename T> void Swap(T *a ,T *b,int n) { T temp; for(int i=0;i<n;i++) { temp =a[i]; a[i]=b[i]; b[i]=temp; } }
模板局限性
某些时候,类型T的相应操作只适用于数组,如果T为结构体则模板函数便不成立
同样,如if(a>b)
,如果T为结构,则>便不成立
解决方案:
- 重载运算符号
- 为特定类型提供具体化模板定义
显示具体化
当编译器找到与函数调用匹配的具体化定义时,将使用该定义,不再寻找模板。
- 对于给定的函数名,可以有非模板函数、模板函数和显示具体化模板函数以及各自的重载版本。
- 显示具体化的原型和定义以
template<>
开头,并通过名称来指出类型 - 调用顺序是:非模板函数>具体化模板函数>模板函数
void Swap(job& ,job&); template <typename T> void Swap(T&,T&); template<> void Swap<job>(job& ,job&);//显示具体化 //Swap<job>中<job>是可选的,因为函数的参数类型表明,这是job的一个具体化,所以也可以这样写: template<> void Swap(job& ,job&);
实例化和具体化
注意:函数模板并不会生成函数定义,他只是生成一个用于生成函数定义的方案,编译器使用模板为特定的类型生成函数定义时,得到的是模板实例。
template<typename T> void Swap(T &a ,T &b); int a =10,b=20; Swap(a,b);//因为提供了int类型的参数,所以自动生成了int类型的模板实例。这样是==隐式实例化== //也可以直接命令编译器创建特定的实例 //显示实例化 template void Swap<int>(int &,int &);//使用Swap()模板生成int类型的函数定义 //显示具体化 template<> void Swap<int>(int& ,int&); template<> void Swap(int& ,int&); //区别在于:具体化是不使用Swap()模板函数生成函数定义,而是使用专门为int类型显示定义的函数定义 //简单的理解,具体化是对函数的声明,而实例化是对模板函数的使用
template<typename T> T Add(T a,T b) { return a+b; } int m=6; double x=10.5; Add<double>(x,m); //与Add(x,m)不匹配,因为一个是int一个是double //通过Add<double>实例化,可强制将m转为double //但是同样的对Swap便不能成功,因为Swap中使用的是引用类型 Swap<double>(m,x);//double& 不能指向int
//使用案例 template <typename T> void Swap(T &,T &); template<> void Swap<job>(job&,job&);//具体化 int mian() { template void Swap<char>(char& ,char&); short a,b; Swap(a,b);//隐式实例化 job n,m; Swap(n,m);//显示具体化 char g,h; Swap(g,h);//显示实例化 }
模板函数类型的确定
template<class T1,class T2> void fun(T1 x,T2 y) { ?type? s=x+y; //因为是模板函数,此时?type?类型不确定 }
C++11增加decltype
关键字
template<class T1,class T2> void fun(T1 x,T2 y) { decltype(x+y) s=x+y; //s类型与x+y的类型一致 }
使用decltype(expression) var
的步骤:
1.如果expression没有用括号括起来,则var与expression类型相同,包括const等限定符
double x =5.5; double& z =x; const double* pd; decltype(x) w; //w为double类型 decltype(z) u; //u为double& 类型 decltype(pd) v; //v为const double* 类型
2.如果expression是一个函数调用,则var与返回值类型相同。并不会实际调用函数,编译器通过查看原型来确定返回值类型
3.如果expression是一个左值,则var为指向其类型的引用。常见的情况如下:
double x = 4.5; decltype((x)) r = x;//r是double&类型 decltype(x) r = x;//r是double类型 //括号不会改变expression的值和左值性 //可理解为加括号仅仅是decltype声明引用的一种方式
4.如果前3条都不满足,则var与expression类型相同
int j=3; int &k=j; int &n=j; decltype(j+6) x; //x是int decltype(k+n) y;//y是int ,虽然k和n是引用,但是k+n不是引用是2个int的和
如果多次声明,可以结合typedef
和decltype
typedef decltype(x+y) xytype; xytype z = x+y; xytype arr[10];
但是某些需定义返回值类型的函数模板任然不能得到解决,如:
template<class T1,class T2> ?type? fun(T1 x,T2 y) //此时无法确定类型 { return x+y; }
C++新增语法auto h(int x,float y) -> double
,这称为后置返回类型,auto是一个占位符
template<class T1,class T2> auto fun(T1 x,T2 y)->decltype(x+y) //后置类型使用decltype { return x+y; }
到此这篇关于C++学习之函数模板的使用详解的文章就介绍到这了,更多相关C++函数模板内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://www.cnblogs.com/qsnn/p/16370860.html
相关文章
- eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
Python astype(np.float)函数使用方法解析
这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08- 这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
- 这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
- strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
PHP函数分享之curl方式取得数据、模拟登陆、POST数据
废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07深入解析WordPress中加载模板的get_template_part函数
这篇文章主要介绍了WordPress中加载模板的get_template_part函数,其中重点讲解了其函数钩子的使用,需要的朋友可以参考下...2016-01-14- Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
- PHP 函数 strip_tags 提供了从字符串中去除 HTML 和 PHP 标记的功能,该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数...2014-05-31
- mysql安装成功后有几个默认的配置模板,列表如下: my-huge.cnf : 用于高端产品服务器,包括1到2GB RAM,主要运行mysql my-innodb-heavy-4G.ini : 用于只有innodb的安装,最多有4GB RAM,支持大的查询和低流量 my-large.cnf : 用于...2015-03-15
- 这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
PHP编码转换函数mb_convert_encoding与iconv用法
文章来实现一个PHP编码转换函数mb_convert_encoding与iconv用法,希望例子能帮助到各位。 将一个短信接口代码从apache迁移到nginx+php-fpm后,发现无法发出短信了,查...2016-11-25php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
最近遇到一个问题,就是在使用php的mail函数发送utf-8编码的中文邮件时标题出现乱码现象,而邮件正文却是正确的。最初以为是页面编码的问题,发现页面编码utf-8没有问题啊,找了半天原因,最后找到了问题所在。 1.使用 PEAR 的...2015-10-21- 本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
- 1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
- php实现数字格式化,数字每三位加逗号的功能函数,具体代码如下: function num_format($num){ if(!is_numeric($num)){ return false; } $num = explode('.',$num);//把整数和小数分开 $rl = $num[1];//小数部分的值...2015-10-23
- 复制代码 代码如下:<?php/***功能:对字符串进行加密处理*参数一:需要加密的内容*参数二:密钥*/function passport_encrypt($str,$key){ //加密函数srand((double)microtime() * 1000000);$encrypt_key=md5(rand(0, 32000...2014-06-07
PHP is_subclass_of函数的一个BUG和解决方法
is_subclass_of的作用:复制代码 代码如下:bool is_subclass_of ( object object, string class_name )如果对象 object 所属类是类 class_name 的子类,则返回 TRUE,否则返回 FALSE。注: 自 PHP 5.0.3 起也可以用一个字符...2014-06-07- 这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 复制代码 代码如下:function getTagStyle(){ $minFontSize=8; //最小字体大小,可根据需要自行更改 $maxFontSize=18; //最大字体大小,可根据需要自行更改 return 'font-size:'.($minFontSize+lcg_value()*(abs($maxFo...2013-10-04