参考
模板类型推导
函数模板可以看成是这样:
template<typename T>
void f(ParamType param);
ParamType param = expr
分三种情况:
- ParamType是一个指针或者引用(非通用universal reference引用)
- ParamType是一个通用引用(universal reference)
- ParamType既不是指针也不是引用
三种情况的推导规则:(推导规则推导的是T的类型)
1
ParamType是一个指针或者引用(非通用universal reference引用)
- 如果expr的类型是引用,忽略引用的部分
- 根据expr和ParamType对比来判断T的类型
2
ParamType是一个通用引用(universal reference)
- 如果expr是个左值,T和ParamType都会被推导成左值引用
- 如果expr是个右值,参考情况1
3
ParamType既不是指针也不是引用
- 如果expr的类型是引用,忽略引用的部分
- expr是cv的,也要忽略cv类型
实际测试:
case 1
1 | template<typename T> |
case 2
1 | template<typename T> |
引用折叠(Reference collapsing)
A&& --> A&
A&&& --> A&
A&&& --> A&
A&& && --> A&&
case2的param经过了引用折叠:
int & && --> int &
const int & && --> const int &
const int & && --> const int &
int && && --> int &&
case 3
1 | template<typename T> |
数组参数
数组会退化为指针:
1 | const char name[] = "J. P. Briggs"; // name的类型是const char[13] |
数组的引用会保留为数组形式:
1 | const char name[] = "J. P. Briggs"; // name的类型是const char[13] |
函数参数
函数类型退化成函数指针:
1 | void someFunc(int, double); //void (int, double) |
函数引用会保留为函数形式:
1 | void someFunc(int, double); //void (int, double) |
auto类型推导
auto类型推导和模板类型推导基本一致,auto相当于T,只有一个例外:{}
1 | auto x1 = 27; //auto: int |
decltype
decltype可以表示变量或者表达式的类型
使用方式:
1 | decltype(expr) a; |
注意点:
对一个变量名使用 decltype 得到这个变量名的声明类型。变量名属于左值表达式,但这并不 影响 decltype 的行为。然而,对于一个比变量名更复杂的左值表达式, decltype 保证返回 的类型是左值引用
1 | int x = 0; |
尾随返回值类型
1 | //c++11版本 |
特殊情况
1 | int main() |
j是左值,类似函数实参(形参是右值的,实参是左值;有名的右值引用是左值)。auto &&这种就是模板的perfect reference