深蓝学院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;
– 其它形式的变量模板

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是Java中的集成测试?

Java中的集成测试&#xff08;Integration Test&#xff09;是一种测试方法&#xff0c;用于测试多个模块或组件之间的交互和集成。在Java中&#xff0c;集成测试通常使用单元测试框架&#xff08;如JUnit&#xff09;编写和运行。 对于初学者来说&#xff0c;集成测试可能有些…

【C/C++】类之间的纵向关系——继承的概念

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

六、初始化和清理(2)

本章概要 垃圾回收器 finalize() 的用途你必须实施清理终结条件垃圾回收器如何工作 垃圾回收器 程序员都了解初始化的重要性&#xff0c;但通常会忽略清理的重要性。毕竟&#xff0c;谁会去清理一个 int 呢&#xff1f;但是使用完一个对象就不管它并非总是安全的。Java 中有…

分享一篇详尽的关于如何在 JavaScript 中实现刷新令牌的指南

介绍 刷新令牌允许用户无需重新进行身份验证即可获取新的访问令牌&#xff0c;从而确保更加无缝的身份验证体验。这是通过使用长期刷新令牌来获取新的访问令牌来完成的&#xff0c;即使原始访问令牌已过期也是如此。 通常&#xff0c;当用户登录时&#xff0c;服务器会生成一对…

CentOS 8 上安装 Nginx

Nginx是一款高性能的开源Web服务器和反向代理服务器&#xff0c;以其轻量级和高效能而广受欢迎。在本教程中&#xff0c;我们将学习在 CentOS 8 操作系统上安装和配置 Nginx。 步骤 1&#xff1a;更新系统 在安装任何软件之前&#xff0c;让我们先更新系统的软件包列表和已安…

关于提示词 Prompt

Prompt原则 原则1 提供清晰明确的指示 注意在提示词中添加正确的分割符号 prompt """ 请给出下面文本的摘要&#xff1a; <你的文本> """可以指定输出格式&#xff0c;如&#xff1a;Json、HTML提示词中可以提供少量实例&#xff0c;…

大数据面试题:Kafka的单播和多播

面试题来源&#xff1a; 《大数据面试题 V4.0》 大数据面试题V3.0&#xff0c;523道题&#xff0c;679页&#xff0c;46w字 参考答案&#xff1a; 1、单播 一条消息只能被某一个消费者消费的模式称为单播。要实现消息单播&#xff0c;只要让这些消费者属于同一个消费者组即…

nosql之redis集群

文章目录 一.redis集群1.单节点redis服务器带来的问题2.集群redis3.集群的优势4.redis集群的实现方法5.redis群集的三种模式5.1 主从复制5.2 哨兵5.3 集群 二.Redis 主从复制1.主从复制概念2.主从复制的作用3.主从复制流程4.搭建Redis 主从复制4.1 安装 Redis4.2 修改 Redis 配…

【C++学习笔记】extern “c“以及如何查看符号表

如何查看符号表 要查看.a文件的内容&#xff0c;可以使用ar命令。下面是一些常见的用法&#xff1a; 列出.a文件中包含的所有文件&#xff1a; ar t <filename.a>提取.a文件中的单个文件&#xff1a; ar x <filename.a> <filename.o>将.a文件中的所有文件提…

【iToday】涵盖100+技术网站的一站式资讯平台 | 文末送书

里面包含了上百个IT网站&#xff0c;欢迎大家访问&#xff1a;http://itoday.top/#/ iToday&#xff0c;打开信息的新时代。作为一家创新的IT数字媒体平台&#xff0c;iToday致力于为用户提供最新、最全面的IT资讯和内容。里面包含了技术资讯、IT社区、面试求职、前沿科技等诸多…

Python实现GA遗传算法优化循环神经网络回归模型(LSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

【学习笔记】关于RAW图片的概念学习

这里是尼德兰的喵芯片设计相关文章&#xff0c;欢迎您的访问&#xff01; 如果文章对您有所帮助&#xff0c;期待您的点赞收藏&#xff01; 让我们一起为成为芯片前端全栈工程师而努力&#xff01; 前言 能为我介绍一下raw图片吗&#xff1f; 当谈论"Raw图片"时&am…

019 - STM32学习笔记 - Fatfs文件系统(一) - FatFs文件系统初识

019 - STM32学习笔记 - Fatfs文件系统&#xff08;一&#xff09; - FatFs文件系统初识 最近工作比较忙&#xff0c;没时间摸鱼学习&#xff0c;抽空学点就整理一点笔记。 1、文件系统 在之前学习Flash的时候&#xff0c;可以调用SPI_FLASH_BufferWrite函数&#xff0c;将数…

Windows 11 上使用 Docker 安装 SQL Server 2022 数据库

Windows 11 上使用 Docker 安装 SQL Server 2022 数据库&#xff0c;你可以按照以下步骤进行操作&#xff1a; 安装 Docker Desktop for Windows&#xff1a; 访问 Docker 官方网站&#xff08;https://www.docker.com/get-started&#xff09;下载并安装适用于 Windows 的 Do…

“RWEQ+”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写

土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160.74104km2&#xff0c;占国土总面积的16.7%&#xff0c;严重影响这些地区的资源开发和社会经…

SpringBoot原理分析 | 安全框架:Shiro

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Shiro Shiro是一个安全框架&#xff0c;用于认证、授权和管理应用程序的安全性。它提供了一组易于使用的API和工具&#xff0c;可以帮助您轻松地添加安全性到您的应用…

2.10 Android ebpf帮助函数解读(九)

161.struct task_struct *bpf_get_current_task_btf(void) 描述:返回一个指向"current"的BTF指针。这个指针可以用来在帮助函数中接收一个task_struct类型的ARG_PTR_TO_BTF_ID。 返回值:返回指向当前task的指针。 162.long bpf_bprm_opts_set(struct linux_binpr…

iOS开发-hook之Method Swizzle更改原有方法实现流程

iOS开发-hook之Method Swizzle更改原有方法实现流程 一 Hook是什么&#xff1f; Hook 简介 Hook&#xff0c;中文译为“挂钩”或“钩子”。通过hook可以让别人的程序执行自己所写的代码。 一段程序的执行流程是 A -> B -> C&#xff0c;现在我们在 A 和 B 之间插入一…

一款基于过滤器的线程共享变量的清理机制

项目中常常用到线程共享变量。如多个函数或对象之间传递参数。循环读取缓存或数据库时时用共享变量减少读取次数。某类特殊对象的持有等。一般用finally去强制释放共享变量。但释放时机有时并不能准确的把握。为此&#xff0c;基于过滤器写了个个释放机制。 过滤器如下&#x…

ubuntu22.04 DNSSEC(加密DNS服务) configuration

/etx/systemd/resolved.conf是ubuntu下DNS解析服务配置文件&#xff0c;systemd为ubuntu下system and service配置目录 step 1——修改resolved.conf参数 管理员权限打开 /systemd/resolved.conf sudo nano /etc/systemd/resolved.conf修改如下&#xff1a; # This file i…