一文讲清C++14的Type-Deduction
记录一下Type-Deduction:
总结自:CppCon 2014: Scott Meyers "Type Deduction and Why You Care"
文章目录
Type-Deduction 简介
在C++98中,Type-Deduction仅用于Template
中,仅有by-value,by-reference,by-ptr规则相对简单。C++11增加了通用引用,auto/decltype
关键字和lambda
。C++14增加了decltype(auto)
,Type-Deduction变化多了。大多数情况下不用考虑Type。但在有些时候,尤其是你要泛化代码,不了解当前Type类型尤其是value还是reference
会产生恼人的bug。
最简单的,对于By-Value的模板函数,如果传入一个引用参数,你可能会困惑为什么模板函数之外的外部变量没有同步修改。第二个例子:auto a = {1}
与auto a{1}
是两种不同的类型,写错可能编译失败或是不知情调用了另外的重载函数。对于函数返回,如果不清楚auto
和decltype(auto)
区别,会把类型搞错,甚至访问失效的内存。
C++ 在以下情况下要考虑Type-Deduction:
1.模板中的T*, T& 及 T&& 等
2.auto关键字
3.decltype
4.lambda capture
5.function的return
6.template class (不做介绍,T与外部传入的变量类型一致)
一、Template规则
顾名思义,Template
规则用于Template
模板中,分为以下3个小规则:
- 非通用引用及指针 (by-nonURef/by-pointer)
简单一句话:外部类型去掉pointer或reference作为T的类型
引用的例子:
// 对于T& 和 const T&
template<typename T>
void foo(T& param) {
} //能接受左值或左值引用为参数
template<typename T>
void fooConst(const T& paramConst) {
} //不接受右值引用,其余皆可(含右值)
// 外部调用:
ExternParamType expr;
foo(expr);
fooConst(expr);
// 对于这两个模板都有:
T = std::remove_reference<ExternParamType>::type;
// 因此第一个模板函数参数(param)类别为"
typeof(param) = std::remove_reference<ExternParamType>::type&;
// 第二模板函数参数(paramConst)类别为:(T本身带Const)
typeof(paramConst) = const std::remove_reference<ExternParamType>::type&;
指针的例子:
// 对于T*
template<typename T>
void foo(T* param) {
}
// 外部调用为
ExternParamType expr;
foo(expr);
// T的类型为
T = std::remove_pointer<ExternParamType>::type;
// 因此模板函数参数(param)类别为"
typeof(param) = std::remove_pointer<ExternParamType>::type*;