关于auto的语法auto specifier
之前看过EffectiveModernC++的 模版类型推导部分,下面总结一下auto类型推导的规则。
推导原则
如果看过了模版类型推导其实auto类型推导是几乎完全一致的。在这二者之间存在一个直接映射的关系。
在模版类型推导中使用以下原型解释
template<typename T>
void f(ParamType param);
f(expr);
当使用auto来声明变量时,auto相当于上述T,auto的一些装饰符(const、volatile、&等)与T组合(type specifier)成了ParamType。
auto x = 27; //T = auto -> int, ParamType = auto = int
const auto cx = x; //T = auto->int ,ParmaType = const int
编译器进行auto类型推导是就好像存在一个模版函数调用,对其T、ParamType进行推导(除了一个例外)
同样也是类似模版类型推导分为三类来进行推导。只不过是根据type specifier来划分。
初始化推导例外
//初始化一个初值为27的变量,直接声明类型
int x1 = 27;
int x2(27);
//对于c++11
int x3 = {27};
int x4{27};
//初始化一个初值为27的变量,采用auto
auto x1 = 27;
auto x2(27);
//对于c++11
auto x3 = {27};
auto x4{27};
以上代码前两个即是声明初始化了27的变量,而后两个却是声明并初始化了std::initializer_list<int>
。当使用auto声明的变量采用{}来初始化时,推导的类型为std::initializer_list<T>
auto 类型推导对比模版类型推导例外
//使用initializer_list来调用函数模版不能推导成功
auto x = {1, 2, 3}; // auto->initializer_list
template<typename T>
void f(T param);
f({1, 2, 3}) //错误,模版类型推导不可推导出T = int
//解决办法
template<typename T>
void f(std::initialzer_list<T> param); //正确,T=int
f({1, 2, 3})
可见,auto类型推导和模版类型推导真正的区别是:auto类型推导将{}初始化方法看作initializer_list类型,但模版类型推导却不这样做。这个陷阱导致非必要情况下不要使用{}初始化。
在C++14中
1.允许使用auto来说明函数返回类型需要类型推导。但是,使用的推导的方式为模版类型推导。
auto function(){
return {1, 2, 3};//错误,模版类型推导不支持initializer_list
}
2.在lambda表达式中,允许对参数使用auto。但是同样使用的是模版类型推导策略。
auto my_lambda = [](const auto& t){};
my_lambda({1, 2, 3}); //错误,模版类型推导不支持initializer_list