引子
模板类型推导与auto类型推导是具有映射关系的。
auto扮演T的角色,而类型限定符扮演ParamType的角色。
与模板类型推导相比,auto仅有一种特殊情况。
template<typename T>
void f(ParamType param)
auto x = 27; //类型限定符就是auto
const auto cx = x; //类型限定符是const auto
const auto& rx = x; //类型限定符是const auto&
正文
Case 1和Case 3:
auto x = 27; //对应Case 3
const auto cx = x; //对应Case 3
const auto& rx = x; //对应Case 1
Case 2也如预期一样:
auto&& uref1 = x; //x是int左值,所以uref1是int&
auto&& uref2 = cx;//cx是const int左值,所以uref2是const int&
auto&& uref3 = 27; //27是int右值,uref3是int&&
auto推导也包含数组和函数隐式转换为指针的情况(没有引用类型限定符的情况下):
const char name[] = "R. N. Briggs";
auto arr1 = name; //arr1's type is const char*
auto& arr2 = name; //arr2's type is const char(&)[13]
void someFunc(int, double);
auto func1 = someFunc; //fun1's type is void (*)(int, double)
auto& func2 = someFunc; //fun2's type is void (&)(int, double)
上述讨论是auto与模板参数推导相似的部分。下面来看例外的情况:
int x1 = 27;
int x2(27);
int x3 = {27};
int x4{27};
auto x1 = 27;
auto x2(27);
auto x3 = {27};
auto x4{27};
使用int显示声明变量类型的表达式,将x1/x2/x3/x4都初始化为一个int类型初值为27的变量;而使用auto声明的变量,x1/x2是int类型初始为27的对象,x3/x4是类型为initializer_list<int>的列表,且包含一个为27的元素。
即,在使用{}进行变量初始化时,auto会使用特殊的类型推导规则,除非类型无法被推导(如{}内的变量具有不同类型):
auto x5 = {1, 2, 3.0}; //error
template<typename T>
void f(T param);
f({11,23,9}); //error
template<typename T>
void f(std::initializer_list<T> initlist);
f({11,23,9}); //T deduced as int
总结
- auto类型推导与模板类型推导规则一致,但是遇到{}会推到成initializer_list
- 函数返回值或lambda表达式参数中的auto是模板类型推导,而不是auto类型推导