今天在一个开源项目中看到一个模板的使用,便想着重新复习这块的内容。

重新翻看以前看过的书籍,发现好多地方都留下了问题,后面也没有再去研究了,再次看到还是一脸懵 。

这一次我结合网上别人的理解和自己动手实践,总算有了一点理解,便把他记录下来,便于以后观看。

template <typename T>
struct identity
{typedef T type;
};template <typename T = int>
void func(typename identity<T>::type val, T = 0)
{//
}int main()
{func(123);                //T -> intfunc(123, 123,0);         //T -> doublereturn 0;
}在例子中, 通过identity外敷模板禁用了形参val的类型自动推导。但由于func指定了模板参数T的默认类型为int,因此,在func(123)中,func的val参数将为int类型。
而在func(123,123.0)中,由于func的第二个参数123.0为double类型,模板参数T将优先被自动推导为double,因此,此时val的参数将为double类型。

如上所示,书中说identity外敷类禁用了形参的val的类型自动推导,我一直不明白这句话是什么意思。直到我自己动手写了这样一段代码:

#include <iostream>using namespace std;template <typename T>
void func(T t1, T t2 = 0)
{return ;
}int main()
{func(123, 123.0);return 0;
}

我将外敷模板的代码去掉,改成直接使用模板类型。在编译时发现编译不通过,错误如下:

test.cpp: In function ‘int main()’:
test.cpp:13:17: error: no matching function for call to ‘func(int, double)’13 |  func(123, 123.0);|                 ^
test.cpp:6:6: note: candidate: ‘template<class T> void func(T, T)’6 | void func(T t1, T t2 = 0)|      ^~~~
test.cpp:6:6: note:   template argument deduction/substitution failed:
test.cpp:13:17: note:   deduced conflicting types for parameter ‘T’ (‘int’ and ‘double’)13 |  func(123, 123.0);|                 ^

这里报错说没有匹配到函数 func(int, double), 看到这里我想我大概明白上面说的禁用形参自动推导的意思了。

然后我再将外敷类的代码加上去,发现能正常编译和运行。

为了验证书中第一段代码中的最后一句话,我将代码改成了这样:

#include <iostream>using namespace std;template <typename T>
struct identity
{typedef T type;
};template <typename T>
T func(typename identity<T>::type t1, T t2)
{cout << "t1:" << t1 << endl;cout << "t2:" << t2 << endl;return t1 + t2;
}int main()
{cout << func(123, 123.0) << endl;return 0;
}

发现打印如下:

t1:123
t2:123
246
怎么都是整形的啊,并不是double类型的啊。

模板函数在编译时都会实例化具体的函数,可以通过可执行文件中函数的符号来查看编译器给这个函数的具体化是什么样的。

通过这个命令查找可执行文件的符号表:nm a.out | grep func

0000000000001286 W _Z4funcIdET_N8identityIS0_E4typeES0_

然后再通过这个符号反推出他的函数名:c++filt _Z4funcIdET_N8identityIS0_E4typeES0_
double func<double>(identity<double>::type, double)

确实是double类型的。

这里还涉及到一个函数模板的默认参数的问题。

template <typename T = int>
void func(typename identity<T>::type val, T = 0)

在这段代码中, T = 0,我以前一直不理解他是什么意思,今天我才明白他就是一个函数的默认参数,只不过这个参数的类型是一个模板参数类型。

总结:

1、在使用模板函数时,如果不指定模板参数类型,那么编译器就会帮我们自动推导。

2、当我们将模板函数的形参类型再进行包装(比如使用外敷类)时,就是禁用掉编译器的自动类型推导,在调用时就需要指明参数类型。

3、当函数中的参数不使用或者在头文件中声明时可以不写参数名(普通函数时是知道的,模板函数一时没反应过来 )。

书中还有一些总结性的话,一并写在这里了:

1、当所有模板参数都有默认参数时,函数模板的调用如同一个普通函数。对于类模板而言,哪怕所有参数都有默认参数,在使用时也必须在模板名后跟随"<>"来实例化。

2、函数模板的默认模板参数不必要写在参数表最后。(我的理解:模板参数的顺序并不等于在函数参数中使用的顺序,所以不必要写在最后)书上这里还有一句话,在调用函数模板时,显示指定的模板参数,其填充顺序是从右往左(这点我测试了,不是这样的。指定的模板参数是从左往右填充的)。

模板函数与模板参数自动推导相关推荐

  1. C++17尝鲜:类模板中的模板参数自动推导

    目录 模板参数自动推导 示例 自定义类模板中的应用 Automatic deduction guides(自动推断向导) 模板参数自动推导 在C++17之前,类模板构造器的模板参数是不能像函数模板的模 ...

  2. 传智播客PHP笔记05-thinkphp框架-视图渲染、display,fetch,模板替换,模板变量的赋值与实现,系统变量,模板函数,模板运算符,foreach,if,比较标签,volist标签

    1.视图概述 将具体的视图模板进行输出显示,有两个方法 display:获取具体要输出的内容,然后直接输出 fetch:获取具体要输出的内容,但不会自动输出 2.display的使用(输出模板内容) ...

  3. ecshop小京东模板切换到smarty3.13之模板函数,用模板函数替换楼层

    ecshop小京东的模板中用到了楼层的概念,看下了模板每个楼层都写了一下,用几个楼层就写了几段,个人感觉这样的有点冗余,不如做个函数,直接循环一下 有两种方法,第一种是:写个函数来实现楼层的显示,第二 ...

  4. [c++][语言语法]函数模板和模板函数 及参数类型的运行时判断

    参考:http://blog.csdn.net/beyondhaven/article/details/4204345 参考:http://blog.csdn.net/joeblackzqq/arti ...

  5. 模板函数限制参数为特定类型

    问题 最近要写一个模板函数,要求是必须被指定的类型才能执行,未被指定的类型要求报错. 注册器模板类 其实所谓接受指定类型作为参数就是对类型进行注册,凡是注册过的类型才能传入模板,非注册类型应当匹配失败 ...

  6. 函数模板、类模板(含模板特化)

    目录 一.函数模板 1.为什么要使用函数模板? 2.函数模板的定义及其使用 3.函数模板的实现原理 4.特例:同名非模板函数能和同名模板函数 同时存在 二.类模板 1.类模板格式 2.使用类模板创建对 ...

  7. [转]C++函数模板与模板函数

    1.函数模板的声明和模板函数的生成 1.1函数模板的声明 函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计.它的最大特点是把函数使用的数据类型作为参数. 函数模板 ...

  8. C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则

    类模板 函数模板 泛型编程 泛型编程,泛型即是指具有在多种数据类型上皆可操作的含义,其实就是能够帮助开发者编写完全一般化并可重复使用的算法,同样的工作不需要做多次,同样的算法针对不同的类型也不应该写多 ...

  9. C++之模板类模板函数

    模板类 模板类的定义使用template<typename T>或template<class T>,将具有相同功能的代码合并,增加代码的简洁性和易读性.例如在计算凸包的例子中 ...

  10. C++基础:模板:函数模板和类模板

    模板: 为了代码重用,代码就必须是通用的:通用的代码就必须不受数据类型的限制. 那么我们可以把数据类型改为一个设计参数.这种类型的程序设计称为参数化(parameterize) 程序设计. 软件模块由 ...

最新文章

  1. 对象存在性检测集中管理
  2. 使用多个DNS供应商以缓解DDoS攻击
  3. 15岁大学毕业,一生800多篇专著论文,双眼失明却凭一条公式称霸数学界
  4. CF1109D Sasha and Interesting Fact from Graph Theory
  5. mysql独立开发_nacos的mysql独立部署
  6. 系统学习深度学习(三十)--BiLSTM
  7. matlab——diff函数
  8. 使用c语言的多学科协同仿真软件,Multisim10软件在单片机C语言协同仿真中应用.pdf...
  9. 模拟人生java电脑版_模拟人生免费版电脑版
  10. 快速从B站下载视频到本地(无需安装软件)
  11. 论文-Interactive Path Reasoning on Graph for Conversational Recommendation
  12. [Asp.net Core]局部视图
  13. 大数据工程师就业前景及发展方向分析
  14. 【tensorflow学习之路】如何使用gpu进行运算
  15. 长程蓝牙温湿度及光照度传感器 , 带四通道开关及指示灯(集成太阳能微能量采集功能)
  16. 不能打开要写入的文件,软件安装不上解决方法
  17. 三坐标检测之测头补偿原理
  18. 没基础不用怕,零基础无需任何技术学重装电脑系统
  19. 计算机导论以python为舟大纲,清华大学出版社-图书详情-《计算机科学导论——以Python为舟(第3版)》...
  20. 超级好的截图工具HprSnap

热门文章

  1. 问答WAP版重新改版上线
  2. win7仿win8主题
  3. swftool pdf2swf使用
  4. 精选的 Go 框架,库和软件的精选清单
  5. lomboz连接mysql数据库_将Lomboz Eclipse 连接上 Oracle 11g
  6. ServerGuide U盘安装Windows Server 2008 R2安装
  7. Premiere Pro 2020 安装教程
  8. 第十二章 WebService框架CXF
  9. 《Linux运维实战:免费md5解密工具》
  10. 【回归预测-ELM预测】基于樽海鞘算法结合极限学习机实现风电场功率回归预测附matlab代码