Deducing Types
模板类型推导
template<typename T>
void f(ParamType param);
编译期间,编译器使用expr进行两个类型推导,一个是针对T,另外一个是针对ParamType的。两个类型通常不同。
因为ParamType通常包括对const和reference的修饰
如:
template<typename T>
void f(const T& param);
模板类型T的推导不仅仅取决于实参,也取决于ParamType的类型。
下面要分三种情况讨论:
ParamType是指针或者引用,但不是通用引用
规则如下:
如果expr的类型是一个引用,会忽略引用部分
然后剩下的部分决定T,让T与形参决定最终的ParamType
eg:
template<typename T>
void f(T & param); //param是一个引用
int x=27; //x是int
const int cx=x; //cx是const int
const int & rx=cx; //rx是指向const int的引用
推导结果:
f(x) // T为int,ParamType为int&
f(cx) // T为const int,ParamType为const int &
f(rx) // T为const int,ParamType为const int &
传const int & 参数的时候,会忽略引用语义,模板参数被推导为const int
ParamType是通用reference
如果函数模板为T,通用引用即T&&
- 如果expr是左值
T和ParamType会被推导为左值引用
template<typename T>
void f(T&& param); //param现在是一个通用引用类型
int x=27; //如之前一样
const int cx=x; //如之前一样
const int & rx=cx; //如之前一样
f(x) //T为 int&, param也是
f(cx) //T为 const int&, param也是
f(rx) //T为 const int&, param也是
- 如果expr是右值
就使用第一条例子
f(27) // T为 int(忽略引用语义), param为int&&
ParamType是传值
template<typename T>
void f(T param);
无论传递什么东西,param都会成为其一份拷贝——一个新的对象。
类型推导的时候,如果expr是一个引用,忽略这个引用。并且也会忽略const和volatile
int x=27; //如之前一样
const int cx=x; //如之前一样
const int & rx=cx; //如之前一样
f(x); //T和param都是int
f(cx); //T和param都是int
f(rx); //T和param都是int
要牢记,传值给形参的时候,要忽略常量性和易变性。
如:
template<typename T>
void f(T param); //传值
const char* const ptr = //ptr是一个常量指针,指向常量对象
" Fun with pointers";
- 左边的const表示字符串是cosnt
- 右边的const表示这个char指针是const,即这个ptr不能修改为指向其他地址
所以实际上param的类型是 const char * , 也就是说指针的自身的常量性将会被忽略。
数组实参
- 传值
template<typename T>
void f(T param);
const char name[] = "J. P. Briggs"; //name的类型是const char[13]
f(name);
如果函数的形参是一个数组:
void myFunc(int param[]);
会等价为一个指针形参
void myFunc(int *param);
所以模板参数类型T会被推导为const char *
- 传引用
template<typename T>
void f(T& param);
如果传的是引用,T会被推导为真正的数组。
函数实参
函数类型也会退化为指针
void someFunc(int, double); //someFunc是一个函数,类型是void(int,double)
template<typename T>
void f1(T param); //传值
template<typename T>
void f2(T & param); //传引用
f1(someFunc); //param被推导为指向函数的指针,类型是void(*)(int, double)
f2(someFunc); //param被推导为指向函数的引用,类型为void(&)(int, bouel)
总结
在模板类型推导时,有引用的实参会被视为无引用,他们的引用会被忽略
对于通用引用的推导,左值实参会被特殊对待
对于传值类型推导,实参如果具有常量性和易变性会被忽略
本文是Effective Modern C++读书笔记的第一部分,主要探讨类型推导,包括模板类型推导的不同情况:ParamType是普通指针或引用、通用引用、传值以及数组和函数实参的情况。强调了在类型推导过程中,编译器如何处理const、引用和值传递的影响。
1018

被折叠的 条评论
为什么被折叠?



