《Effective Modern C++》条款1:模板类型推导

本文深入探讨了C++模板类型推导的细节,包括ParamType为指针或引用、万能引用以及常规拷贝类型的情况。通过具体例子阐述了如何根据expr和ParamType确定模板参数T的类型,特别强调了const、引用和指针在类型推导中的作用。同时,介绍了数组参数的特殊推导方式以及利用模板获取数组大小的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本章节主要针对于template的类型推到进行一个简介;

对于一下template模板:

template<typename T> 
void fun(ParamType param);

fun(expr);

以往自己认为T的类型是由expr来决定的,之后作用于ParamType,但是今天看了这张发现自己的理解有点问题;

事实情况是T的类型是什么取决于ParamType以及expr的具体形式,并不是孤立存在的;

因此,T的类型不仅取决于expr的类型,也取决于ParamType的类型;

本章节对ParamType分了三种场景,并且结合expr的类型,对T的推断进行讨论;

分别为三种情况:

  1. ParamType为指针或者引用(不是右值万能引用);
  2. ParamType为万能引用;
  3. ParamType既不是指针,也不是引用;

1. ParamType是指针或引用:

template<typename T>
void fun(T& param);

fun(expr);

对于该种情况,主要有两条严格规律:

(1)expr的引用类型会被忽略;
个人认为原因是由于param已经为引用,因此如果T不能再推断为引用,否则将变为万能引用形式;

(2)之后对expr的型别和ParamType的型别执行匹配,来确定T的型别;
主要目的是确定其他修饰符,例如const等是否参与类型推导;

例如:

const int& rx=x;

f(rx);//T的类型被推导为const int,param的类型是const int&;

对于上述的rx,首先剥除引用,之后由于为const int,所以T应该为const int,从意愿上我们也希望const对象传入后,也应该当作为const类型在模板中进行处理;

再比如:

template<typename T>
void f(const T& param);

const int& rx=x;

f(rx);//T的类型被推导为int,param的类型是const int&;

从上述可看,由于形参已经带有const,所以T就没必要带const;

针对于指针类型也是同理:

template<typename T>
void f(T* param);

const int* rx=x;

f(rx);//T的类型被推导为const int,param的类型是const int*;

推断方法和上述类似,因此T的具体类型取决于expr和Param两者共同作用;

2. ParamType是万能引用:

这点和右值引用有关;

template<typename T>
void fun(T&& param);

fun(expr);

对于如果传输的是右值,需要右值引用来接收该值,但是实际模板推导不一定传输的为右值,也有可能为左值;

对于该种情况,则针对于模板实例化进行判断:

如果是左值,则改为左值的引用,因为右值不允许直接接收左值;

如果为右值,则直接接收,获取类型;

例如:

const int& x=27;
fun(x);//左值,降级去引用,用于是const引用,所以T为const int&;

fun(25);//右值,应该为右值引用,所以为fun的形参应该为int&&,T为int;

3. ParamType常规拷贝类型:

形式如下:

template<typename> 
void fun(T param)

此时可以认为形参为实参的拷贝,因此常规的const对象可能被忽略;

因此有两条经典规则:
(1)应该忽略expr的引用情况;
(2)如果为const对象,即不可修改,由于值拷贝的特性,也应该给予忽略;

但是针对于const类型,有一种情况需要注意一下;

对于指针也可以采用拷贝类型进行参数判断,考虑指针

const char* const ptr="123"

f(ptr);//此时应该判断为char* const类型;

const char* const 为一个常量指针指向一个常量;

但是值拷贝只能消除常量指针特性,但是还是只能指向常量,因此类型判断应该是char* const;

关于数组实参:

传统数组存在降级的问题,也就是一个数组指针会被判断为一个单指针;

但是这里提出了一种新的可以推导数组的方法,并且可以用于辅助其他数组实例化;

template<typename T>
void f(T& param);

f(name);//此时被推导为const char& [n],其中n为name数组的大小;

因此,可以用于实例化之中;

template<typename T,std::size_t N>
constexpr std::size_t arrSize(T (&)[N]) noexcept{
	return N;
}

int keys[]={1,2,3,4,5,6};
int new_array[arrSize(keys)];

可以在便编译期间利用该函数获得数组大小,用于后续的赋值;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值