《C++ Primer》 读书笔记——第十六章 模板与泛型编程

第十六章 模板与泛型编程

16.1 定义模板

1. 函数模板

写法

在这里插入图片描述
在函数开头加上:template
其中模板参数T表示要传入的类型

实例化函数模板

在这里插入图片描述
当编译器实例化一个模板时,它使用实际的模板实参代替对应的模板参数来创建出模板的一个新“实例”。(创建一个新的版本)

非类型模板参数

在这里插入图片描述
非类型模板参数是一个值而非一个类型
在这里插入图片描述

inline和constexpr修饰的函数模板

在这里插入图片描述
inline在模板参数列表之后,在函数返回类型之前

泛型编码的两个重要原则

在这里插入图片描述
第一个原则是为了避免复制从而提高效率,同时保证不更改引用的参数而加上const
第二个原则是为了减少对函数实参类型的要求,系统定义的类对<运算支持得比较广泛,如果使用了其他运算符号,可能会需要添加新的关系运算符。

函数模板和类模板成员函数的定义通常放在头文件中

一般的函数和类声明和定义都要分离

2. 类模板

写法举例

在这里插入图片描述
和模板函数类似,以
template <typename T>
开头,在类中使用类型参数T构造相应的变量和函数

实例化类模板

在这里插入图片描述
常用的有容器vector的实例化

类模板的成员函数

类模板的成员函数本身是一个普通的函数。但是,类模板的每个实例都有自己版本的成员函数
类模板的成员函数具有和模板相同的模板参数。
定义在类模板之外的成员函数必须以关键字template开始,后接类模板参数列表
在这里插入图片描述

类模板的构造函数

在这里插入图片描述

成员函数的实例化

一个类模板的成员函数只有用到它的时候才进行实例化

类模板和友元

一对一友好关系:某个特定实例和某个特定实例
在这里插入图片描述
定义类的友元时附带上相同的类型参数

通用和特定的模板友好关系:一个类与另一个模板的每个实例
在这里插入图片描述
友元附带上不同的类型信息:C2和Pal2,C2的每一个实例都与所有的Pal2实例是友元

让模板自己的参数类型成为友元
在这里插入图片描述

类模板的static成员

每个实例(不同类型)都有自己的静态成员,所有实例化类型的对象(同一类型的不同对象)共享相同的静态成员

可以通过对象来访问,也可以通过类加上作用域来访问
在这里插入图片描述

3. 模板参数

可以使用作用域运算符访问static成员和类型成员(类型成员就是在类里面自定义的类型)
在这里插入图片描述
此处假定一个类T,里面含有自定义类型value_type

默认模板实参

在这里插入图片描述

4. 成员模板

成员模板的写法

一个类的成员函数是模板函数,这种成员称之为成员模板。成员模板不能是虚函数。
在这里插入图片描述

成员模板的调用

成员模板的调用和普通模板函数一样,根据实参推断类型
在这里插入图片描述

类模板的成员模板

类是模板,里面含有成员模板

定义:需要提供两个类型实参
在这里插入图片描述

5. 控制实例化

在这里插入图片描述
在这里插入图片描述

16.2 模板实参推断

从函数实参来确定模板实参的过程被称为模板实参推断。
编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定的函数调用最为匹配。

1. 类型转换与模板类型参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 函数模板显式实参

在这里插入图片描述
这时候可以由用户显式指定模板的实参:
在这里插入图片描述

3. 尾置返回类型与类型转换

在这里插入图片描述
当返回类型为传入的模板类型时,可以使用尾置返回类型。
在这里插入图片描述
在这里插入图片描述
函数头的返回值使用auto占位,后面使用尾置推断出返回类型

进行类型转换的标准库模板类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 函数指针和实参推断

用函数模板初始化函数指针时,编译器使用指针的类型来推断模板实参
在这里插入图片描述
pf1为函数指针,通过函数指针的类型可以得到模板函数中的类型参数

5. 模板实参推断和引用

从左值引用函数参数推断类型

在这里插入图片描述
函数参数是类型参数的左值引用时,会出现上述情况

从右值引用函数参数推断类型

在这里插入图片描述
函数参数是类型参数的右值引用

引用折叠和右值引用参数

规则1:将左值传递给右值引用的函数参数并且该函数参数的类型为类型参数,编译器推断模板类型为实参的左值引用类型
在这里插入图片描述
规则2:
在这里插入图片描述
在这里插入图片描述
例子:
在这里插入图片描述

16.3 重载与模板

函数模板可以被另一个模板或一个普通非模板函数重载。
在这里插入图片描述

编写重载模板

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多个可行模板

在这里插入图片描述

非模板和模板重载

非模板的普通函数也可以和模板函数组成重载函数
在这里插入图片描述
非模板函数的匹配会优先于模板函数,因为它更加特例

缺少声明可能导致程序行为异常

在这里插入图片描述
如果忘记了非模板类型函数的声明,则编译器会将模板函数实例化来使用。实例化的模板函数可能与我们写的非模板函数含义不符。

16.4 可变参数模板

在这里插入图片描述
参数的数目是可变的

表示方法

在函数参数中用省略号来表示,在类型参数中用typename…来表示
在这里插入图片描述

1. 编写可变参数函数模板

在这里插入图片描述
第一个版本终止递归,第二个版本负责递归(每次从参数包中取出一个)

2. 包扩展

理解上一点中的程序就知道怎么扩展了
在这里插入图片描述

16.5 模板特例化

在这里插入图片描述
不从模板中生成实例,而是我们自己写一个实例

1. 定义函数模板实例化

在这里插入图片描述
template加上空的尖括号对<>

2. 函数重载与模板特例化

将特例化的模板函数视为一个普通的非模板函数,它的匹配优先级比模板函数要更高

3. 类模板特例化

类的模板也可以特例化:
在这里插入图片描述

4. 类模板部分特例化

指定一部分模板参数
在这里插入图片描述
在这里插入图片描述

5. 特例化成员而不是类

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值