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

本文详细介绍了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,照理说intconst intconst 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(
评论 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、付费专栏及课程。

余额充值