深蓝学院C++基础与深度解析笔记 第13章 模板

1. 函数模板

● 使用 template 关键字引入模板:

 template<typename T>              //声明:T模板形参
 void fun(T);                      // T 函数形参
             
 template<typename T>              //定义
 void fun(T) 
 {...}
– 函数模板不是函数
– typename 关键字可以替换为 class ,含义相同
– 函数模板中包含了两对参数:函数形参 / 实参;模板形参 / 实参

● 函数模板的显式实例化(生成函数): fun<int>(3)

– 实例化会使得编译器产生相应的函数(函数模板并非函数,不能调用)
– 编译期的两阶段处理
  ● 有限的模板语法检查
  ● 模板实例化
– 模板必须在实例化时可见,  翻译单元的一处定义原则 
– 注意与内联函数的异同:都是翻译单元的一处定义原则,模板是调用,内联是引入 

● 函数模板的重载
参数个数重载:
在这里插入图片描述
参数重载为指针:
在这里插入图片描述
● 模板实参的类型推导 :参考文献

– 如果函数模板在实例化时没有显式指定模板实参,那么系统会尝试进行推导
– 推导是基于函数实参(表达式)确定模板实参的过程,其基本原则与 auto 类型推导相似
   ● 函数形参是左值引用 / 指针:
        – 忽略表达式类型中的引用
        – 将表达式类型与函数形参模式匹配以确定模板实参
   ● 函数形参是万能引用
         int&& x = 3; 
         – 如果实参表达式是右值,确定值那么模板形参被推导为去掉引用的基本类型
        – 如果实参表达式是左值,那么模板形参被推导为左值引用,触发引用折叠
   ● 函数形参不包含引用
        – 忽略表达式类型中的引用
        – 忽略顶层 const
         – 数组、函数转换成相应的指针类型
   ● 第一个函数形参十分重要

在这里插入图片描述
● 模板实参并非总是能够推导得到

– 如果模板形参与函数形参无关,则无法推导
– 即使相关,也不一定能进行推导,推导成功也可能存在因歧义而无法使用

● 在无法推导时,编译器会选择使用缺省模板实参

– 可以为任意位置的模板形参指定缺省模板实参 注意与函数缺省实参的区别 
函数参数有默认值的时候,它的右边的参数一定要有默认值,
模板参数有默认值的时候,它的右边的参数不一定要有默认值,

● 显式指定部分模板实参

– 显式指定的模板实参必须从最左边开始,依次指定
– 模板形参的声明顺序会影响调用的灵活性

● 函数模板制动推导时会遇到的几种情况

– 函数形参无法匹配—— SFINAE (替换失败并非错误)
– 模板与非模板同时匹配,匹配等级相同,此时选择非模板的版本
– 多个模板同时匹配,此时采用偏序关系确定选择 最特殊 的版本

● 函数模板的实例化控制

– 显式实例化定义(只声明先不调用 ): template void fun<int>(int) / template void fun(int)
– 显式实例化声明: extern template void fun<int>(int) / extern template void fun(int)
– 注意一处定义原则
– 注意实例化过程中的模板形参推导,按代码出现顺序

● 函数模板的 ( 完全 ) 特化: 注意尖括号
template<> void f<int>(int) / template<> void f(int)
本质是一个实例

– 并不引入新的(同名)名称,只是为某个模板针对特定模板实参提供优化算法,
– 注意与重载的区别
– 注意特化过程中的模板形参推导

● 避免使用函数模板的特化: 视频参考资料

– 不参与重载解析,会产生反直觉的效果
– 通常可以用重载代替
– 一些不便于重载的情况:无法建立模板形参与函数形参的关联,可以 
    ● 使用 if constexpr 解决
    ● 引入假函数形参 “ ”
    ● 通过类模板特化解决

●(C++20) 函数模板的简化形式:使用 auto 定义模板参数类型

– 优势:书写简捷
– 劣势:在函数内部需要间接获取参数类型信息

2. 类模板与成员函数模板

● 使用 template 关键字引入模板: template<typename T> class B {…};

– 类模板的声明与定义 翻译单元的一处定义原则 ——
– 成员函数只有在调用时才会被实例化,节省空间
– 类内类模板名称的简写
– 类模板成员函数的定义(类内、类外)
  ● 模板类内可以有模板函数

● 成员函数模板

– 类的成员函数模板
– 类模板的成员函数模板

● 友元函数(模板)

– 可以声明一个函数模板为某个类(模板)的友元
– C++11 支持声明模板参数为友元,but 用途不大

● 类模板的实例化: 更多内容

– 与函数实例化很像
– 可以实例化整个类,或者类中的某个成员函数

● 类模板的(完全)特化 / 部分特化(偏特化)

– 特化版本与基础版本可以拥有完全不同的实现

● 类模板的实参推导(从 C++17 开始)

– 基于构造函数的实参推导
– 用户自定义的推导指引
– 注意:引入实参推导并不意味着降低了类型限制!
– C++ 17 之前的解决方案:引入辅助模板函数

3. Concepts

● 模板的问题:没有对模板参数引入相应的限制

– 参数是否可以正常工作,通常需要阅读代码进行理解
– 编译报错友好性较差 (vector<int&>)

● ( C++20 ) Concepts :编译期谓词,基于给定的输入,返回 true 或 false进行限制

– 与 constraints ( require 从句)一起使用限制模板参数
– 通常置于表示模板形参的尖括号后面进行限制

● Concept 的定义与使用
– 包含一个模板参数的 Concept:

  ● 使用 requires 从句
  ● 直接替换 typename

– 包含多个模板参数的 Concept:

  ● 用做类型 constraint 时,少传递一个参数,推导出的类型将作为首个参数

● requires 表达式

– 简单表达式:表明可以接收的操作
– 类型表达式:表明是一个有效的类型:typename
– 复合表达式:表明操作的有效性,以及操作返回类型的特性
– 嵌套表达式:包含其它的限定表达式,也可以包含requires嵌套

● 注意区分 requires 从句与 requires 表达式

●requires 从句会影响重载解析与特化版本的选取

– 只有 requires 从句有效而且返回为 true 时相应的模板才会被考虑
– requires 从句所引入的限定具有偏序特性,系统会选择限制最严格的版本

● 特化小技巧:在声明中引入“ A||B” 进行限制,之后分别针对 A 与 B 引入特化

4. 模板相关内容

数值模板参数与模板模板参数
● 模板可以接收(编译期常量)数值作为模板参数

template <int a> class Str; //数值要有一个类型template <typename T, T value> class Str;(C++ 17) template <auto value> class Str;(C++ 20) 接收字面值类对象与浮点数作为模板参数
   ● 目前 clang 12 不支持接收浮点数作为模板参数

● 接收模板作为模板参数

template <template<typename T> class C> class Str;(C++17) template <template<typename T> typename C> class Str;
–  C++17 开始,模板的模板实参考虑缺省模板实参(clang 12 支持程度有限)

● Str 是否支持?

别名模板与变长模板
● 可以使用 using 引入别名模板

– 为模板本身引入别名
– 为类模板的成员引入别名
– 别名模板不支持特化,但可以基于类模板的特化引入别名,以实现类似特化的功能
  ● 注意与实参推导的关系,要求确定能推导出来才行

● 变长模板( Variadic Template )
在这里插入图片描述

– 变长模板参数与参数包
– 变长模板参数可以是数值、类型或模板
– sizeof...  操作
– 注意变长模板参数的位置

包展开与折叠表达式

●(C++11) 通过包展开技术操作变长模板参数

– 包展开语句可以很复杂,需要明确是哪一部分展开,在哪里展开

●(C++17) 折叠表达式 (cpp reference)

– 基于逗号的折叠表达式应用
– 折叠表达式用于表达式求值,无法处理输入(输出)是类型与模板的情形

完美转发与 lambda 表达式模板
● (C++11) 完美转发: std::forward 函数
– 通常与万能引用结合使用
– 同时处理传入参数是左值或右值的情形
●(C++20) lambda表达式模板

歧义与变量模板
● 使用 typename 与 template 消除歧义

– 使用 typename 表示一个依赖名称是类型而非静态数据成员
– 使用 template 表示一个依赖名称是模板
– template 与成员函数模板调用

●(C++14) 变量模板
– template T pi = (T)3.1415926;
– 其它形式的变量模板

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/52712.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

指针进阶详解---C语言

❤博主CSDN:啊苏要学习 ▶专栏分类&#xff1a;C语言◀ C语言的学习&#xff0c;是为我们今后学习其它语言打好基础&#xff0c;C生万物&#xff01; 开始我们的C语言之旅吧&#xff01;✈ 目录 前言&#xff1a; 一.字符指针 二.指针数组 三.数组指针 四.数组、指针参数 …

阿里云服务器全方位介绍_优势_使用_租用费用详解

阿里云服务器全方位介绍包括云服务器ECS优势、云服务器租用价格、云服务器使用场景及限制说明&#xff0c;阿里云服务器网分享云服务器ECS介绍、个人和企业免费试用、云服务器活动、云服务器ECS规格、优势、功能及应用场景详细你说明&#xff1a; 目录 什么是云服务器ECS&…

Games101学习笔记 - 基础数学

向量 向量&#xff1a;方向和长度&#xff0c;没有起始位置 向量长度&#xff1a;各个方向平方相加开方 单位向量&#xff1a;向量除向量的长度 点乘 在笛卡尔坐标系中的点乘计算&#xff1a; 几何意思&#xff1a; 表示一个向量在另一个向量上的投影点乘在图形学中应用&a…

opencv-23 图像几何变换02-翻转-cv2.flip()

在 OpenCV 中&#xff0c;图像的翻转采用函数 cv2.flip()实现 &#xff0c;该函数能够实现图像在水平方向翻转、垂直方向翻转、两个方向同时翻转&#xff0c;其语法结构为&#xff1a; dst cv2.flip( src, flipCode )式中&#xff1a;  dst 代表和原始图像具有同样大小、类…

安卓:JzvdStd——网络视频播放器

目录 一、JzvdStd介绍 JzvdStd的特点和功能&#xff1a; JzvdStd常用方法&#xff1a; 二、JzvdStd使用 1、补充知识&#xff1a; 例子&#xff1a; MainActivity &#xff1a; VideoPageAdapter &#xff1a; activity_main&#xff1a; video_page&#xff1a; …

iOS 应用上架流程详解

iOS 应用上架流程详解 欢迎来到我的博客&#xff0c;今天我将为大家分享 iOS 应用上架的详细流程。在这个数字化时代&#xff0c;移动应用已经成为了人们生活中不可或缺的一部分&#xff0c;而 iOS 平台的 App Store 则是开发者们发布应用的主要渠道之一。因此&#xff0c;了解…

2024考研408-计算机网络 第一章-计算机网络体系结构学习笔记

文章目录 前言一、计算机网络概述1.1、概念及功能1.1.1、计算机网络的概念1.1.2、计算机网络的功能功能1、数据通信功能2、资源共享功能3、分布式处理功能4、提高可靠性&#xff08;分布式处理引申功能&#xff09;功能5、负载均衡&#xff08;也是分布式处理引申功能&#xff…

机器学习的关键词和算法总结

随着全球各行业的数据治理、数字化转型智能化辅助的引入发展&#xff0c;机器学习&#xff08;包括深度学习&#xff09;在逐步深入到各行各业&#xff0c;所以&#xff0c;有必要对机器学习的常见术语&#xff0c;经典算法及应用场景进行一次总结&#xff0c;其实机器学习兴起…

Java Design and development -- QQ chat

About ARTS - Complete one ARTS per week: ● Algorithm: Do at least one LeetCode algorithm per week Review: Read and comment on at least one technical article in English ● Tips: Learn at least one technical trick ● Share: Share a technical article with op…

基于新浪微博海量用户行为数据、博文数据数据分析:包括综合指数、移动指数、PC指数三个指数

基于新浪微博海量用户行为数据、博文数据数据分析&#xff1a;包括综合指数、移动指数、PC指数三个指数 项目介绍 微指数是基于海量用户行为数据、博文数据&#xff0c;采用科学计算方法统计得出的反映不同事件领域发展状况的指数产品。微指数对于收录的关键词&#xff0c;在指…

指针应用基础练习

&#xff08;1&#xff09;一级指针&#xff0c;二级指针 void getString(char **p) {*p "hello world"; }int main(void) {char *str NULL;getString(&str);printf("%s\n", str); } 代码分析&#xff1a; 定义了一个char型指针str&#xff0c;…

Vue 3:玩一下web前端技术(五)

前言 本章内容为VUE语法的简单学习与相关语法讨论。 上一篇文章地址&#xff1a; Vue 3&#xff1a;玩一下web前端技术&#xff08;四&#xff09;_Lion King的博客-CSDN博客 下一篇文章地址&#xff1a; Vue 3&#xff1a;玩一下web前端技术&#xff08;六&#xff09;_L…

复习之linux存储的基本管理

一、实验环境的设定 1. 实验环境的搭建 本节内容只需要一台虚拟机 westosa reset重置虚拟机&#xff0c;保证实验环境的纯净配置网络实现ssh连接 重置虚拟机后&#xff0c;配置网络&#xff0c;设定ip&#xff1a;172.25.254.100&#xff0c;保证与主机可以通信 实现ssh连接…

chatgpt 接口使用(一)

使用api实现功能 参考链接&#xff1a;https://platform.openai.com/examples 安装库&#xff1a; pip3 install openai 例如&#xff1a; import os import openaiopenai.api_key os.getenv("OPENAI_API_KEY") response openai.ChatCompletion.create(model&q…

配置tomcat内存大小(windows、linux)

一、参数说明 -Xms&#xff1a; JVM初始分配的堆内存 -Xmx&#xff1a; JVM最大允许分配的堆内存&#xff0c;按需分配 -XX:PermSize&#xff1a; JVM初始分配的非堆内存 -XX:MaxPermSize&#xff1a; JVM最…

QT服务器练习

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this); }Widget::~Widget() {delete ui; }//启动服务器按钮对…

阿里云域名备案

最好的爱情&#xff0c;不是因为我们彼此需要在一起&#xff0c;而是因为我们彼此想要在一起。 阿里云的域名如何备案&#xff0c;域名备案和ICP备案一样吗&#xff1f;&#xff1f; 截至我所掌握的知识&#xff08;2021年9月&#xff09;&#xff0c;阿里云的域名备案和ICP备案…

什么是嵌入式软件开发?

嵌入式软件一般是在交叉的开发环境下进行的&#xff0c;这样的运行环境能够让软件开发过程中更加稳定、可靠和安全&#xff0c;在很大程度上提升了软件开发的质量和效率&#xff0c;同时也使得软件开发的难度和程度大大降低。 嵌入式软件的交叉开发环境&#xff0c;反映了用于…

Spire.Office for.NET Crack

Spire.Office for.NET Crack Spire.Office for.NET是E-iceblue提供的企业级Office.NET API的组合。它包括Spire.Doc、Spire.XLS、Spire.Seadsheet、Spire.Presentation、Spire_PDF、Spire.DataExport、SpireOfficeViewer、Spire-PDFViewer、Spire.DocViewer、Spire.Barcode和Sp…

windows版docker部署springcloud项目

材料&#xff1a; 1.windows版docker环境&#xff08;其他版教程可能道理一样但是比如文件后坠名上可能有差异&#xff09; 2.运行好的数据库容器&#xff08;实现教程&#xff09; 3.所有jar包 实现&#xff1a; 最后整好的文件夹结构图&#xff08;原工程文件机密&#xf…