C++模板元编程详细教程(之二)

C++编译流程 C/C++是编译型高级语言,程序要执行,必须要有编译器和链接器。编译过程分为四步:预处理、编译、汇编、链接。 阅读详情
AI摘要

本文详细介绍了C++模板的自动类型推导机制,包括根据函数参数和构造参数自动推导模板参数类型的方法,以及如何使用推导指南来自定义构造推导。

先序文章请看C++模板元编程详细教程(之一)

模板参数自动推导

在上一章我们讲解了C++模板的基本用法,并且强调了模板并非直接可用的代码,需要经历「实例化」,而实例化的过程其实就是指定参数的过程。

但如果模板只能通过显式指定参数来进行实例化的话,那C++模板的「威力」也就止步于此了,进而也就不会出现复杂的模板元编程体系这样的东西。所以C++模板还有一个非常重要的特性,就是模板参数的自动推导。

模板参数的自动推导主要分为3种:

  1. 根据函数参数自动推导(模板函数)
  2. 根据构造参数自动推导(模板类)
  3. 自定义构造推导(模板类)

需要强调的一点是,自动推导只能推导类型参数,而整数和整数派生参数是没法推导的,只能靠显式传入。

下面就来逐一介绍。

根据函数参数自动推导

本条针对的是模板函数。再次强调,模板参数和函数参数是不同的东西,用于实例化模板的参数是模板参数,用于调用函数的参数是函数参数。直观上来说,尖括号里的是模板参数,圆括号里的是函数参数。

我们先来看一个例子:

template <typename T>
void show(T t) {
   
   
  std::cout << t << std::endl;
}

void Demo() {
   
   
  int a = 5;
  show(a); // [1]
  show(5); // [2]
}

在上述例程中,show是一个模板函数,在下面两处标记的位置我们是直接调用show的,而没有指定模板参数,那么这时,就会触发模板参数的自动推导。

先来看一下[1]位置的调用,由于我们传入了参数a,编译器就会根据a的类型来推导模板参数T。在模板函数show的声明处,参数列表是(T t),所以T会根据a的类型来推导。那么问题来了,这里到底会推导出int还是int &还是const int还是const int &?

答案也很简单,模板参数的自动推导是完全按照auto的推导原则进行的。(如果读者对这部分还不是很清楚的话可以参考《C++的缺陷和思考(三)》中「auto推导策略」章节的内容。)

也就是说,这里相当于auto t = a;,会推导出int,因此T会推导出int。

同理,针对于[2]位置的调用,我们传入的是一个常量5,照理说int、const int、const int &、int &&、const int &&都可以匹配,但根据auto的推导原则,仅仅保留「最简类型」,所以仍然会推导出int。

那么[1]和[2]的位置其实相当于:

show<int>(a); // [1]
show<int>(5); // [2]

再次强调,推导的原则与auto相同。那么同样地,也就支持和*、&、&&、const的组合,下面给出几个实例:

template <typename T>
void f1(T &t) {
   
   }

template <typename T>
void f2(const T &t) {
   
   }

template <typename T>
void f3(T *p) {
   
   }

void Demo() {
   
   
  f1(5); // 会报错,因为会推导出f1<int>,从而t的类型是int &,不能绑定常量
  int a = 1;
  f1(a); // f1<int>,t的类型是int &
  f2(a); // f2<int>,t的类型是const int &
  f3(a); // 会报错,因为会推导出f3<int>,此时t的类型是int *,int不能隐式转换为int *
  f3(&a); // f3<int>, t的类型是int *
}

这里需要注意的是,T是按照auto法则来推导的,但由于我们加上了修饰符,所以实际的函数参数t的类型是会带上这种描述符的,详情可以看上面例程的注释。

既然模板参数类型推导是按照auto法则,那就不得不提到一个特殊的推导,它就是auto &&。我们知道auto &&会根据绑定对象的左右性来推导出左值引用或是右值引用。(如果读者对这部分不清楚的话,可以参考《C++的缺陷和思考(二)》中「引用折叠」章节的内容。)同理对于用&&修饰的参数,在自动推导时也会拥有这样的特性。

换句话说,T &&也可以绑定可变值,此时会推导出左值引用。请看下面例程:

template <typename T>
void f4(T &&t) {
   
   }

void Demo(
C++模板元编程详细教程(之一) 《C++模板元编程详细教程》系列文章的第一篇,主要介绍了模板的概念以及基本的模板语法和相关示例。 阅读详情

相关推荐

C++中模板类的编译过程

首先要明白,C++中每一个对象所占的空间大小,对象的内存分布

u011201045的专栏 2372

C++模板元编程详细教程(之十一)

《C++模板元编程详细教程》系列的第11篇,也是完结篇,主要介绍了visit的实现方法、C++的模板范式,以及一些Q&A和感悟

fl2011sx的博客 3674

C++模板元编程详细教程(之五)

《C++模板元编程详细教程》系列文章的第5篇,主要介绍了模板元编程两大要素的第一要素——静态数值计算

fl2011sx的博客 4551

C++模板元编程详细教程(之四)

《C++模板元编程详细教程》系列文章的第4篇,主要介绍了偏特化匹配和SFINAE

fl2011sx的博客 3774

C++模板元编程详细教程(之七)

《C++模板元编程详细教程》的第7篇,主要介绍一些高级的类型处理方式,以及void_t的用法

fl2011sx的博客 3116

C++模板元编程详细教程(之三)

《C++模板元编程详细教程》系列文章的第3篇,主要介绍的是模板的链接方式和模板的特化

fl2011sx的博客 4010

C++高阶必会操作--模板元编程

泛型编程大家应该都很熟悉了,主要就是利用模板实现“安全的宏”,而模板元编程区别于我们所知道的泛型编程,它是一种较为复杂的模板,属于C++的高阶操作了,它最主要的优点就在于把计算过程提前到编译期,能带来可观的性能提升。接下来,一起来学习吧。 1、概述 模板元编程(Template Meta programming,TMP)是编写生成或操纵程序的程序,也是一种复杂且功能强大的编程范式(Programming Paradigm)。 C++模板给C++提供了元编程的能力,但大部分用户对 C++ 模板的使用并不

kxtxdy的博客 6172

C++模板元编程详解

C++模板是支持泛型编程的重要特性,允许编写与类型无关的代码,提升代码复用性和灵活性。模板分为函数模板和类模板,分别用于生成通用函数和类。模板参数包括类型参数、非类型参数和模板模板参数。模板实例化是编译器根据具体类型生成代码的过程,而模板特化则允许为特定类型提供特殊实现。模板元编程(TMP)利用模板在编译时进行计算或生成代码,结合constexpr、SFINAE、类型萃取、可变参数模板等技术,实现编译期计算和类型操作。

weixin_43484713的博客 1843

C# ArcGIS Engine二次开发——实现“加载shp文件”

private void AddShpDataToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog OpFileDialog=new OpenFileDialog();//OpenFileDialog:打开文件对话框 OpFileDialog.Title="添加矢量数据"; OpFileDialog.Filter="(*.shp)|*.shp";//filter:过滤器;"(*.shp)|*.shp"

weixin_42191203的博客 5254

随机子空间集成方法原理与scikit-learn实践

集成学习通过组合多个基学习器的预测结果来提升模型性能,是机器学习中的核心方法之一。随机子空间方法作为集成学习的重要变体,其核心原理是通过对特征空间进行随机子采样来增加模型多样性。这种方法特别适合处理高维数据,能有效缓解维度灾难问题,常与决策树、K近邻等对特征选择敏感的基学习器配合使用。在scikit-learn中,可以通过BaggingClassifier和BaggingRegressor实现随机子空间集成,关键参数包括max_features和n_estimators。实际应用中,该方法在金融风控、医疗诊

weixin_33773084的博客 377

CANoe VLAN配置的艺术:如何通过脚本自动化实现高效车载网络测试

本文深入探讨了CANoe VLAN配置的自动化实现,通过CAPL脚本与Python工具链的结合,提升车载网络测试效率。重点解析了硬件侧VLAN配置与软件侧VLAN配置的交互机制,并提供了实用的脚本开发示例和调试技巧,帮助工程师快速构建高效的自动化测试方案。

qqq44的博客 615

【解决问题】‘vue‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

【解决问题】'vue' 不是内部或外部命令,也不是可运行的程序或批处理文件。

weixin_44566194的博客 4万+

Protobuf NDK以及QNX交叉编译

Protobuf 用处很广,尤其是通讯数据序列化,反序列化。TODO。

静虚待令,有物混成 1559

从理论到实践:基于Zemax的高分辨率生物显微镜光学系统仿真与优化指南

本文详细介绍了基于Zemax的高分辨率生物显微镜光学系统仿真与优化全流程。从阿贝分辨率公式、柯勒照明等理论基础出发,逐步讲解Zemax建模、像差优化、制造可行性分析等核心步骤,并提供常见问题解决方案。通过实际案例展示如何将理论设计转化为可制造的优化方案,帮助工程师掌握从仿真到实际应用的关键技术。

weixin_29229989的博客 480

通信算法之283:大疆DJI云哨系统-DJI DroneID物理层协议-解速率匹配及Turbo译码

3. 完整云哨接收机,接收灵敏度。交流: 1279682290 ,2. Turbo译码模块。1. 解速率匹配模块。

leegang12的专栏 867

第244篇 视觉SLAM后端之BA优化——Bundle Adjustment的原理

本文介绍了SLAM后端优化中的Bundle Adjustment(BA)技术。BA通过同时优化相机位姿和3D路标点位置,最小化重投影误差,解决前端估计的累积误差问题。文章详细讲解了BA的数学原理,包括目标函数构建、Gauss-Newton法和Levenberg-Marquardt法求解过程,以及利用稀疏性和Schur补加速计算的关键技术。对比了全量BA和增量BA的优缺点,并介绍了Ceres、g2o等工程实现工具。BA作为SLAM后端的核心算法,其理解深度直接影响系统性能优化能力。

郑伟强dev的专栏 344

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: C++模板元编程详细教程(之一)
下一篇: 用C++实现各种设计模式(一)
borehole打洞哥
博客等级 码龄11年 545粉丝 81原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

borehole打洞哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值