第一章 型别推导

本文详细解析C++模板型别推导的规则,包括引用处理、auto推导原理,以及decltype的应用实例。重点讲解了模板参数推导、auto推导与初始化列表的关系,并讨论了数组和函数实参的退化。理解这些概念有助于提升对高级C++类型系统的掌握。
摘要由CSDN通过智能技术生成

仅供复习和查看用途,欢迎各位进行友善的讨论交流

item 1:理解模板型别推导

模板和调用的一般形式

template<typename T>
void f(ParamType param);
  
  f(expr);		// 根据expr推导T和ParamType

T的型别推导不仅依赖于expr,还依赖于ParamType,具体如下

情况1:ParamType为指针或引用,型别推导的运作
1)若expr具有引用型别,忽略引用(如果实参是引用,在这种情况下引用性会被忽略掉)
2)对expr和ParamType的型别进行匹配,来决定T的型别

template<typename T>
void f(const T &param);
int x =0;
const int cx = x;
//由于假定param具有const引用,T的型别推到中含有const也就没有必要了
f(x);	//T:int ,param:const int&
f(cx);	//T:int, param:const int&

情况2:ParamType是万能引用
1)如果为左值,T和ParamType都会推到为左值引用(T被推导为型别的唯一情形)
2)如果expr为右值,对用情况1;

template<typename T>
void f(T &&param);
int x =0;
const int cx = x;
//由于假定param具有const引用,T的型别推到中含有const也就没有必要了
f(x);	//T:int& ,param:int&
f(cx);	//T:const int&, param:const int&

情况3:ParamType既不是指针也非引用
1)若expr具有引用型别,忽略引用
2)忽略引用性之后,const和volatile也忽略之
试着考虑这种情形:

const char * const ptr = "hello world";
f(ptr); //哪一个const会被挥发掉?顶层const表示指针本身是个常量,底层const表示所指的对象是常量

数组实参和函数实参

template<typename T>
void f(T param);//T推导成const char *
或者
template<typename T>
void f(T &param);//T推导成const char [N]

template <typename T, size_t N>
constexpr size_t ArraySize(T (&)[N]) noexcept{
    cout<< "size:"<<N<<endl; //输出size:6
}
int main ()
{
  const char ptr[] = "hello";
  ArraySize(ptr);
  return 0;
}

小结

  1. 模板推导中,引用性会被忽略
  2. 万能引用形参推导时,左值进行特殊处理(引用折叠)
  3. 按值传递形参,忽略const和volatile
  4. 数组和函数型别的实参退化为对应的指针,除非被用来初始化引用

item 2:理解auto推导

在一般情况下,auto型别推导和模板推导是一样的,但是auto推导会假定使用大括号的初始化表达式是std::initializer_list

// 这里会发生两种推导,第一种源于auto的使用,x需要推导为std::initializer_list,
// 但由于是模板类,需要根据某个型别T产生实例对象,std::initializer_list<T>意味着
// T也必须被推导出来,进行二级推导
auto x = {1, 2, 3 };

由于模板只能进行一级推导,因此下面代码推导失败

template<typename T>
void f(T param); // 若指定为std::initializer_list<T> 则可以通过编译
f({1, 2, 3});

以上是关于c++11的auto内容,对于c++14使用auto来说明函数返回值需要推导,以及lambda表达式也会在形参中使用auto,这些用法是在使用模板推导而非auto推导(也就是只能进行一级推导)

item 3:理解decltype

// 万能引用搭配std::forward(相对于右值引用搭配std::move)
template<typename Container, typename Index>
decltype(auto)  //c++14 ,c++11使用尾置返回
func(Container && c, Index i){
	...
	return std::forward<Container>(c)[i];
}

特殊情况:只要左值表达式不仅是一个型别为T的对象,就得出一个T&

int x = 0; // decltype(x) : int, decltype((x)) : int&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值