1、通过一个简单的例子来理解模板的用途:

模板为不同类型的数据生成操作相同或相似的函数。
弱语言如Python,可以使用一种函数来应对各种类型,但是C++就不得不为不同的类型编写相似的函数。模板的作用就是把这一步骤交给编译器去执行,让这些函数在编译器生成。
 
2、模板参数的自动推导
原则:凡是可以推导出来的模板参数“值”就无需在模板实参列表中写明。
规则一:编译器值根据函数调用时给出的实参列表来推导模板参数值,与函数参数类型无关的模板参数无法推导
规则二:与函数返回值相关的模板参数其值也无法推导
规则三:所有可以推导模板参数必须是连续位于模板参数列表尾部,中间不能有不可退到的模板参数。
举例:
 

test1~test3的分析过程如下:
第一,sv2是返回值,我们不能通过返回值的类型推导模板参数的值,所以T2无法推导出来;
第二,T0使用的地方是函数内部的一个变量,也不是函数的参数,所以无法通过sv0的类型推导出T0的值
第三,以test1为例,func的三个参数分别是1,2,3整型,所以可以推断出T1、T3、T4是int。因为T0和T2无法推导出,所以必须在func<>中明确给出。而由于要根据声明的顺序给出,不能跳过T1,所以func<>中的三个类型分别是T0、T1、T2的类型。
 
3、模板参数的默认值
形如:
有两个具有默认类型,其它三个可以从函数参数类型推导,所以不需要尖括号:
 
4、模板参数的静态变量
这一讲用来说明,如果模板参数的值是相同的,那么模板函数实例就只生成一个,不会重复生成。
 

test1和test2中的static变量进行了递减,说明test1和test2中的func是同一个。这也就说明,func的实例是依具体的参数而决定的,如果模板参数值一样,编译器就不会重复生成函数实例。
我们逆向也可以知道,这里的两个函数是相同的:

用IDA加载进符号表之后,会更清晰一点:

5、问题一:模板函数应该如何在头文件里声明?
 
如果只是在头文件里添加一个函数模板的声明:

这样编译工程是肯定能编译通过的。因为,编译器在编译test.h和test.cpp文件时,只是读到了func0函数模板的实现,并没有读到任何需要生成函数模板的实例的语句,所以不会生成任何func0函数实例。

但是如果在main.cpp中添加了func0,那么此时就要生成一个func0的具体实例了,但test.h文件中只有一个func0函数模板的声明,编译器并没有生成实际的函数实例,只好在mian函数中的func0处预留一个链接调用,等待在链接过程中找到函数实现。因为你这里调用时,实际上是调用一个func0<int>(0); 但是test.cpp里并没有这个函数的实力。就会报错(这种错误很隐晦,很难排查):

所以,我们的解决办法是明确地在头文件中声明具体的实例。编译器就会生成这个函数模板实例了:

问题二:
但是,如果你想再生成func0(float)、func0(char)那么就得在头文件中添加两个实例的声明。但这貌似违背了最初使用模板的目的。
解决的办法就是把模板的实现也包含到头文件中,这样main函数把test.h包含进来了,编译器在编译时就知道main函数要用到一个func0<int>实例了,就可以编译出func0<int>实例了。//如果你把代码放到cpp里,那就是等到连接时去做事儿,如果放到h文件里,那就是在编译时去做事儿。
 
问题三:
产生重复模板实例问题。但这个问题会由连接器解决。
比如,新增加caller.obj

原有的main.obj中也有

但我们会发现main和caller.obj最终调用的都是caller中的func0:

就是因为连接器把caller0和main中的func0合并成了一个,合并规则是函数名、模板实参列表以及参数列表相同。
 
 
 
 

《深入实践C++模板编程》之一——Hello模板的更多相关文章

  1. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  2. 《深入实践C++模板编程》之四——特例

    1. 所谓模板特例,是针对符合某种条件的模板参数值集合另外声明的模板实现变体. template<typename T> class my_vector; template<> ...

  3. 《深入实践C++模板编程》之二——模板类

    1.类的模板的使用 类,由于没有参数,所以没有模板实参推导机制. #include <stdexcept> template<typename T> class my_stac ...

  4. c++模板编程-typename与class关键字的区别

    最近一直在研究c++模板编程,虽然有些困难,但希望能够坚持下去.今天,在书上看见一个讨论模板编程typename与class两个关键字的区别,觉得挺有意义的,就把它们给总结一下. 先看一个例子: te ...

  5. C++ 11可变参数接口设计在模板编程中应用的一点点总结

    概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...

  6. C++模板编程中只特化模板类的一个成员函数

    模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全 ...

  7. C++之模板编程

    当我们越来越多的使用C++的特性, 将越来越多的问题和事物抽象成对象时, 我们不难发现:很多对象都具有共性. 比如 数值可以增加.减少:字符串也可以增加减少. 它们的动作是相似的, 只是对象的类型不同 ...

  8. c++ 基于Policy 的 模板编程

    在没真正接触c++  模板编程之前.真的没有想到c++ 还能够这么用.最大的感触是:太灵活了,太强大了. 最初接触模板威力还是在Delta3d中,感觉里面的模板使用实在是灵活与方便,特别是dtAI中使 ...

  9. C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)

    转自:https://www.cnblogs.com/zhoug2020/p/6581477.html 模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多 ...

随机推荐

  1. 2018-2019-2 20175227张雪莹《Java程序设计》实验四 《Android程序设计》

    2018-2019-2 20175227张雪莹<Java程序设计> 实验四 <Android程序设计> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学 ...

  2. Linux系统是否被植入木马的排查流程梳理

    在日常繁琐的运维工作中,对linux服务器进行安全检查是一个非常重要的环节.今天,分享一下如何检查linux系统是否遭受了入侵? 一.是否入侵检查 1)检查系统日志 1 2 检查系统错误登陆日志,统计 ...

  3. javascript 数据分组

    一.静态数据 [ {"id":"1001","name":"值1","value":"11 ...

  4. 最新create-react-native-app搭建rn教程

    一.前置条件: 1.nodeJS环境 2.npm 3.yarn 二.安装及项目初始化 1.安装脚手架 npm install -g create-react-native-app 2.用脚手架初始化创 ...

  5. ASP.NET的IIS映射

    ASP.NET默认扩展名为.aspx,可是我们看到许多网站的扩展名很特别,比如校内的do.个性之余还可以实现简单的伪静态(即把后缀改为html) 不过相对URLRewriter来说,是有点简陋(只能改 ...

  6. Spring策略模式的实现

    场景: 有时候一个业务方法有多个实现类,需要根据特定的情形进行业务处理. 例如:商店支付,我们可以使用支付宝.微信扫描农行.xxx行的快捷支付(而不是微信支付.支付宝支付二维码)购买商品. 实现代码( ...

  7. FlexBox布局的重要属性

    /** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { ...

  8. MySQL知识点系统总结

    MySQL数据库是一个非常流行的关系型数据库.配合Linux.PHP.Apache,简称lamp,是一般个人企业网站的首选.MySQL用起来不难,要系统的用好,可不是一件简单的事.于是PHP程序员雷雪 ...

  9. 什么是MapReduce?

    [学习笔记] 什么是MapReduce?马 克-to-win @ 马克java社区:1)MapReduce是面向大数据并行程序设计的模型和方法,这一点很像我们前面讲的MVC,MVC解决动态网站问题而 ...

  10. 爬取汽车之家新闻图片的python爬虫代码

    import requestsfrom bs4 import BeautifulSouprespone=requests.get('https://www.autohome.com.cn/news/' ...