模板型别推导
函数模板及函数代码:
template<typename T>
void f(ParamType param);
f(expr);
在这种情况下,T的型别不仅依赖于expr的型别,还依赖于ParamType的形式。具体情况分为三种:
- ParamType具有指针或者引用型别,但不是万能引用
- ParamType是万能引用
- ParamType不是指针也不是引用
ParamType具有指针或者引用型别,但不是万能引用:
型别推导过程:
- 若expr具有引用或者指针型别,先将引用或者指针部分忽略
- 对expr的型别和ParamType的型别执行模式匹配,来决定T的型别
例:
template<typename T>
void f(T& param);
int x = 10; //x型别int
const int cx = x; //cx型const int
const int& rx = x; //rx型别const int&
f(x); //T的型别int,param型别int&
f(cx);//T的型别const int,param型别const int&
f(rx);//T的型别const int,param型别const int&
template<typename T>
void f(const T& param);
int x = 10; //x型别int
const int cx = x; //cx型const int
const int& rx = x; //rx型别const int&
f(x); //T的型别const int,param型别const int&
f(cx);//T的型别const int,param型别const int&
f(rx);//T的型别const int,param型别const int&
Param是个万能引用
型别推导规则:
- expr如果是左值,T和ParamType都会推导为左值引用(在模板型别推导中,唯一一种T被推导为左值引用的情况)
- expr如果是右值,引用情况1的规则
例:
template<typename T>
void f(T&& param);
int x = 10; //x型别int
const int cx = x; //cx型const int
const int& rx = x; //rx型别const int&
f(x); //x是左值,T的型别int&,param型别int&
f(cx);//cx是左值,T的型别const int&,param型别const int&
f(rx);//rx是左值,T的型别const int&,param型别const int&
f(10);//10是右值,T的型别int,param型别int&&
ParamType不是指针也不是引用
在这种情况下,执行的是值传递,param是传入对象的一个副本,推导规则为:
- 如果expr具有引用型别,忽略引用部分
- 如果expr是个const对象,也忽略const性质,如果是volatile对象,也同样忽略
例:
template<typename T>
void f(T& param);
int x = 10; //x型别int
const int cx = x; //cx型const int
const int& rx = x; //rx型别const int&
f(x); //T的型别int,param型别int
f(cx);//T的型别int,param型别int
f(rx);//T的型别int,param型别int
- 特殊情况,expr是个const char* const ptr
在这种情况下指针自身的const性质不会保留(因为是以复制的方式创建新指针的),而指向对象的const性质是会保留的(符合情况1)。
特殊情况:
- 数组实参
- 函数实参
在模板型别推导中,如果实参是数组或者函数,它们会退化成为指针,除非是用来初始化引用。