条款2:理解auto类型推导
条款1中,模板类型推导的函数模板形如:
template<typename T>
void f(ParamType param);
当变量采用auto
声明时,auto
扮演了模板中的T
这个角色,而变量的类型扮演的是ParamType
的角色。
条款1中的三种情况同样也适用于auto
,只有下面的一点不同。
当用于auto
声明变量的初始化表达式是使用大括号括起时,推导所得的类型就属于std::initializer_list
。但是,如果向对应的模板传入一个同样的初始化表达式,类型推导就会失败。
auto x = {11, 23, 9}; // x的类型是std::initializer_list
template<typename T>
void f(T param);
f({11, 23, 9}); // error,无法推导T的类型
所以,auto和模板类型推导真正的唯一区别在于,auto
会假定用大括号括起的初始化表达式代表一个std::initializer_list
,但模板类型推导却不会。
只有将param
声明为std::initializer_list<T>
,模板类型推导机制会推导出T
应有的类型。
template<typename T>
void f(std::initializer_list<T> initList);
f({11, 23, 9}); // T的类型为int
C++14中,允许使用auto
来说明函数返回值需要推导,lambda表达式中也会在形参声明中用到auto
。然而,这些auto
用法是在使用模板类型推导而非auto
类型推导。
auto createInitList()
{
return {1, 2, 3}; // 错误,无法为{1, 2, 3}完成类型推导
}