C++模板类型推导

12 篇文章 0 订阅
1 篇文章 0 订阅

模板类型推导

对于模板函数来说,编译器需要根据实际传入的参数来推导模板类型T。例如,假设我们有下面这个模板函数:

tempalte<typename T>
void f(T& param); // param si a reference

同时声明了这些变量:

int x = 27;				// x is an int
const int cx = x;		// cx is a const int
const int& rx = x;		// rx is a reference to x as a const int

那么调用模板函数时,编译器推导出的模板类型分别为:

f(x)		// T is int, param's type is int&
f(cx)		// T is const int, param's type is const int&
f(rx)		// T is const int, param's type is const int&

可以发现,同样是整型变量,带不带const、是不是reference,类型推导的结果是不一样的。回到刚开始声明的模板函数,我们声明了参数类型为T&,如果声明为T,或者是T&&,又会得到怎样的结果?我们用表格来总结一下:

xcxrxrvalue
void f(T& param)Tintconst intconst intx
paramint&const int&const int&x
void f(const T& param)Tintintintint
paramconst int&const int&const int&const int&
void f(T&& param)Tint&const int&const int&int
paramint&const int&const int&int&&
void f(T param)Tintintintint
paramintintintint
猛一看表格,会让人眼花缭乱。死记硬背是记不住的,我们找一找其中的规律。
  • 一般情况下,param的类型是最完整的类型,继承了形参中声明的cr(const和reference)和实参总带过来的cr。但有两个特例:
    • 特例一:当形参时通用引用(T&&作为模板参数时称为通用引用)时,param根据具体的实参类型,推导为左值引用或者右值引用;
    • 特例二:当形参不是引用时,实参到形参为值传递,去除所有cr修饰符。
  • T中是否包含cr修饰符,取决于param的修饰符是否已在形参中声明过。也就是说,T中修饰符不会与形参中已声明的修饰符重复。

为什么我们需要知道这些规则呢?这是因为,有时候需要根据传入的param的类型构造与之相关联的其它类型的对象。比如我们想要在函数内部构造一个与param同类型但去除cr修饰符的对象,那么就应该把形参声明为const T& param,然后声明T obj这个对象。这是因为上表中第4行表明了,无论实参包含了什么修饰符,无论是左值还是右值,T都是不带任何修饰符的单纯类型。当然,声明为T param也是可以的,但这种情况下参数就是值传递了。所以说,根据实际情况选择合适的模板参数类型是很重要的。

最后,为了更容易实践,我们总结出下面三个推荐用法:

  • 想要按值传递,将模板函数参数声明为T param
  • 想要按引用传递,但不考虑右值时,将模板函数参数声明为const T& param
  • 想要按引用传递,但要区分左值和右值时,将模板函数声明为T&& param
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值